LINUX.ORG.RU

История изменений

Исправление dissident, (текущая версия) :

Так в этом то и основная идея: избежать использования создания объектов для всего массива

Я правильно понял, что ты хочешь быть кошерным и избежать malloc/free, при этом не вызывая default constructor создавая таблицу objs? Если понял правильно, то в C++ можно сделать так (если пернул в лужу и задача другая, сорри):

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

objs = operator new(sizeof(Object)*width)

Это семантически тоже самое, чтo:

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

operator new(size_t) возвращает continuos memory без вызова конструкторов.

objs[index] = obj;

new (objs+value) Object(obj);
new (&objs[value]) Object(obj); // или так, same shit

Так мы вместо оператора присваивания используем копирующий конструктор, что может быть эффективней (так как ему не надо, например, создавать копию Object чтобы быть exception-safe, тут также может быть вызван move constructor если он есть). Оператор placement new позваляет указать где создать объект.

Обрати внимание, что:

Object* objs = operator new[N];
это функция «operator new», делающая тоже самое, что в C malloc().

а вот

new (p) T();

Это placement operator new, вызывающий конструктор T, но создающи объект в месте указанном указателем p. Т.е. это разные вещи.

Надо помнить, что при использовании placement new нельзя делать

delete objs[value]:

илил

delete[] objs;

Надо руками вызвать деструктор, а потом вызвать функцию «operator delete» (которая по аналогии с функцией «operator new», делает тоже, что free() в C).

// construct() constructs a new object in 
// a given location using an initial value
//
template <class T1, class T2>
void construct( T1* p, const T2& value )
{
  new (p) T1(value);
}

The above form of new is called «placement new,» and instead of allocating memory for the new object, it just puts it into the memory pointed at by p. Any object new'd in this way should generally be destroyed by calling its destructor explicitly (as in the following two functions), rather than by using delete.

// destroy() destroys an object or a range 
// of objects
//
template <class T>
void destroy( T* p )
{
  p->~T();
}

template <class FwdIter>
void destroy( FwdIter first, FwdIter last )
{
  while( first != last )
  {
    destroy( &*first );
    ++first;
  }
}

template <class T> 
StackImpl<T>::~StackImpl()
{
    destroy( v_, v_+vused_ ); // this can't throw
    operator delete( v_ );
}

(c) Herb Sutter «Exceptional C++», item 12 solution

Т.е. каждый элемент obj надо уничтожать так:

objs[i]->~Object();
operator delete(objs+i); // тоже что и free()
operator delete(&objs[i]); // или так, что тоже самое

Исправление dissident, :

Так в этом то и основная идея: избежать использования создания объектов для всего массива

Я правильно понял, что ты хочешь быть кошерным и избежать malloc/free, при этом не вызывая default constructor создавая таблицу objs? Если понял правильно, то в C++ можно сделать так (если пернул в лужу и задача другая, сорри):

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

objs = operator new(sizeof(Object)*width)

Это семантически тоже самое, чтo:

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

operator new(size_t) возвращает continuos memory без вызова конструкторов.

objs[index] = obj;

new (objs+value) Object(obj);
new (&objs[value]) Object(obj); // или так, same shit

Так мы вместо оператора присваивания используем копирующий конструктор, что может быть эффективней (так как ему не надо, например, создавать копию Object чтобы быть exception-safe, тут также может быть вызван move constructor если он есть). Оператор placement new позваляет указать где создать объект.

Обрати внимание, что:

Object* objs = operator new[N];
это функция «operator new», делающая тоже самое, что в C malloc().

а вот

new (p) T();

Это placement operator new, вызывающий конструктор T, но создающи объект в месте указанном указателем p. Т.е. это разные вещи.

Надо помнить, что при использовании placement new нельзя делать

delete objs[value]:

илил

delete[] objs;

Надо руками вызвать деструктор, а потом вызвать функцию «operator delete» (которая по аналогии с функцией «operator new», делает тоже, что free() в C).

// construct() constructs a new object in 
// a given location using an initial value
//
template <class T1, class T2>
void construct( T1* p, const T2& value )
{
  new (p) T1(value);
}

The above form of new is called «placement new,» and instead of allocating memory for the new object, it just puts it into the memory pointed at by p. Any object new'd in this way should generally be destroyed by calling its destructor explicitly (as in the following two functions), rather than by using delete.

// destroy() destroys an object or a range 
// of objects
//
template <class T>
void destroy( T* p )
{
  p->~T();
}

template <class FwdIter>
void destroy( FwdIter first, FwdIter last )
{
  while( first != last )
  {
    destroy( &*first );
    ++first;
  }
}

template <class T> 
StackImpl<T>::~StackImpl()
{
    destroy( v_, v_+vused_ ); // this can't throw
    operator delete( v_ );
}

(c) Herb Sutter «Exceptional C++», item 12 solution

Т.е. каждый элемент obj надо уничтожать так:

objs[i]->~Object();
operator delete(objs+i); // тоже что и free()
operator delete(&objs[i]); // или так, что тоже самое

Исправление dissident, :

Так в этом то и основная идея: избежать использования создания объектов для всего массива

Я правильно понял, что ты хочешь быть кошерным и избежать malloc/free, при этом не вызывая default constructor создавая таблицу objs? Если понял правильно, то в C++ можно сделать так (если пернул в лужу и задача другая, сорри):

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

objs = operator new(sizeof(Object)*width)

Это семантически тоже самое, чтo:

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

operator new(size_t) возвращает continuos memory без вызова конструкторов.

objs[index] = obj;

new (objs+value) Object(obj);
new (&objs[value]) Object(obj); // или так, same shit

Так мы вместо оператора присваивания используем копирующий конструктор, что может быть эффективней (так как ему не надо, например, создавать копию Object чтобы быть exception-safe, тут также может быть вызван move constructor если он есть). Оператор placement new позваляет указать где создать объект.

Обрати внимание, что:

Object* objs = operator new[N];
это функция «operator new», делающая тоже самое, что в C malloc().

а вот

new (p) T();

Это placement operator new, вызывающий конструктор T, но создающи объект в месте указанном указателем p. Т.е. это разные вещи. Правда при этом нельзя делать delete objs[value]:

// construct() constructs a new object in 
// a given location using an initial value
//
template <class T1, class T2>
void construct( T1* p, const T2& value )
{
  new (p) T1(value);
}

The above form of new is called «placement new,» and instead of allocating memory for the new object, it just puts it into the memory pointed at by p. Any object new'd in this way should generally be destroyed by calling its destructor explicitly (as in the following two functions), rather than by using delete.

// destroy() destroys an object or a range 
// of objects
//
template <class T>
void destroy( T* p )
{
  p->~T();
}

template <class FwdIter>
void destroy( FwdIter first, FwdIter last )
{
  while( first != last )
  {
    destroy( &*first );
    ++first;
  }
}

template <class T> 
StackImpl<T>::~StackImpl()
{
    destroy( v_, v_+vused_ ); // this can't throw
    operator delete( v_ );
}

(c) Herb Sutter «Exceptional C++», item 12 solution

Т.е. каждый элемент obj надо уничтожать так:

objs[i]->~Object();
operator delete(objs+i); // тоже что и free()
operator delete(&objs[i]); // или так, что тоже самое

Исправление dissident, :

Так в этом то и основная идея: избежать использования создания объектов для всего массива

Я правильно понял, что ты хочешь быть кошерным и избежать malloc/free, при этом не вызывая default constructor создавая таблицу objs? Если понял правильно, то в C++ можно сделать так (если пернул в лужу и задача другая, сорри):

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

objs = operator new(sizeof(Object)*width)

Это семантически тоже самое, чтo:

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

operator new(size_t) возвращает continuos memory без вызова конструкторов.

objs[index] = obj;

new (objs+value) Object(obj);
new (&objs[value]) Object(obj); // или так, same shit

Так мы вместо оператора присваивания используем копирующий конструктор, что может быть эффективней (так как ему не надо, например, создавать копию Object чтобы быть exception-safe, тут также может быть вызван move constructor если он есть). Оператор placement new позваляет указать где создать объект.

Правда при этом нельзя делать delete objs[value]:

// construct() constructs a new object in 
// a given location using an initial value
//
template <class T1, class T2>
void construct( T1* p, const T2& value )
{
  new (p) T1(value);
}

The above form of new is called «placement new,» and instead of allocating memory for the new object, it just puts it into the memory pointed at by p. Any object new'd in this way should generally be destroyed by calling its destructor explicitly (as in the following two functions), rather than by using delete.

// destroy() destroys an object or a range 
// of objects
//
template <class T>
void destroy( T* p )
{
  p->~T();
}

template <class FwdIter>
void destroy( FwdIter first, FwdIter last )
{
  while( first != last )
  {
    destroy( &*first );
    ++first;
  }
}

template <class T> 
StackImpl<T>::~StackImpl()
{
    destroy( v_, v_+vused_ ); // this can't throw
    operator delete( v_ );
}

(c) Herb Sutter «Exceptional C++», item 12 solution

Т.е. каждый элемент obj надо уничтожать так:

objs[i]->~Object();
operator delete(objs+i); // тоже что и free()
operator delete(&objs[i]); // или так, что тоже самое

Исходная версия dissident, :

Так в этом то и основная идея: избежать использования создания объектов для всего массива

Я правильно понял, что ты хочешь быть кошерным и избежать malloc/free, при этом не вызывая default constructor создавая таблицу objs? Если понял правильно, то в C++ можно сделать так (если пернул в лужу и задача другая, сорри):

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

objs = operator new(sizeof(Object)*width)

Это семантически тоже самое, чтo:

objs = static_cast<Object*>(malloc(sizeof(Object) * width));

operator new(size_t) возвращает continuos memory без вызова конструкторов.

objs[index] = obj;

new (objs+value) Object(obj);
new (&objs[value]) Object(value); // или так, same shit

Так мы вместо оператора присваивания используем копирующий конструктор, что может быть эффективней (так как ему не надо, например, создавать копию Object чтобы быть exception-safe, тут также может быть вызван move constructor если он есть). Оператор placement new позваляет указать где создать объект.

Правда при этом нельзя делать delete objs[value]:

// construct() constructs a new object in 
// a given location using an initial value
//
template <class T1, class T2>
void construct( T1* p, const T2& value )
{
  new (p) T1(value);
}

The above form of new is called «placement new,» and instead of allocating memory for the new object, it just puts it into the memory pointed at by p. Any object new'd in this way should generally be destroyed by calling its destructor explicitly (as in the following two functions), rather than by using delete.

// destroy() destroys an object or a range 
// of objects
//
template <class T>
void destroy( T* p )
{
  p->~T();
}

template <class FwdIter>
void destroy( FwdIter first, FwdIter last )
{
  while( first != last )
  {
    destroy( &*first );
    ++first;
  }
}

template <class T> 
StackImpl<T>::~StackImpl()
{
    destroy( v_, v_+vused_ ); // this can't throw
    operator delete( v_ );
}

(c) Herb Sutter «Exceptional C++», item 12 solution

Т.е. каждый элемент obj надо уничтожать так:

objs[i]->~Object();
operator delete(objs+i); // тоже что и free()
operator delete(&objs[i]); // или так, что тоже самое