Что это за второй новый? - PullRequest
       52

Что это за второй новый?

14 голосов
/ 18 октября 2010

Что такое вторая строка? (При ответе на другой вопрос.)

int * x = new int [1] ;
int * y = new (x) int;

После второй строки x и y имеют одинаковое значение (указывают на одно и то же место). В чем разница между y = x и второй строкой? Это как конструктор или что-то?

Ответы [ 5 ]

13 голосов
/ 18 октября 2010

Это размещение новых .Он создает новый int в памяти, на которую указывает x.

. Если вы попытаетесь:

int * x = new int [1];
*x = 5;
std::cout << *x << std::endl;
int * y = new (x) int;
*y = 7;
std::cout << *x << std::endl;

, то результат будет:

5
7
4 голосов
/ 18 октября 2010

Это называется размещение новых .Он позволяет вам построить объект в уже выделенной памяти.

В этом предыдущем потоке обсуждается , где и как это полезно для .

3 голосов
/ 18 октября 2010

Это новое место размещения.

Хотя вы обычно его не используете с целочисленными типами.
Обычно оно используется для создания буфера, в который вы затем встраиваете другие типы.

// Allocate a buffer with enough room for two T objects.
char* buffer   = new char[sizeof(T) * 2];

// Allocate a T in slot zero
T* t1 = new (buffer + 0 * sizeof(T)) T("Zero");

// Allocate a T in slot one
T* t2 = new (buffer + 1 * sizeof(T)) T("One");

Это основы.
Но помните, что объекты, выделенные с размещением new , не могут быть удалены с помощью оператора delete.Это потому, что delete пытается восстановить память, выделенную new (а также вызвать деструктор).Поэтому, чтобы правильно использовать эти объекты, вы должны вручную вызвать там деструктор.

t1->~T();
t2->~T();

Не забудьте удалить исходный буфер.

delete [] buffer;

Несколько других предостережений:
Людичасто видят, что буфер может быть реализован в стеке и, таким образом, автоматически освобождается

char buffer[sizeof(T) * 2];

К сожалению, это может быть технически нормально (компилируется).Но работа не гарантируется, так как память буфера может быть неправильно выровнена для размещения Т внутри.Таким образом, вы должны динамически распределять буфер (с помощью нового он гарантирует, что память выровнена правильно для любого объекта выделенного размера (таким образом, путем расширения он также выравнивается для любого размера, меньшего, чем выделенный размер). Простой способ обойтиэта проблема заключается в использовании std :: vector

std::vector<char>    buffer(sizeof(T) * 2);
T* t1 = new (&buffer[0] + 0 * sizeof(T)) T("Zero");
T* t2 = new (&buffer[0] + 1 * sizeof(T)) T("One");

Другое использование размещения new - сброс объекта.
Я видел, что это сделано, но я предпочитаю использовать более стандартный оператор присваивания:

T   obj1("Plop");
obj1  = T("Another Plop");

// Can be done like this:
T   obj1("Plop");
obj1.~T();
new (&obj1) T("Another Plop");   // Seems excessive to me. But can be us-full
                                 // in some extreme situations.

Помните, что если вы используете метод сброса, вы должны сначала уничтожить старый объект (или объект может работать неправильно).

3 голосов
/ 18 октября 2010

Второе новое - это «новое размещение». Он выполняет инициализацию (то есть вызывает любые необходимые конструкторы) без какого-либо выделения. Это полезно, когда вам нужно создать собственную схему выделения памяти.

2 голосов
/ 18 октября 2010
int * y = new (x) int; 

Это согласно новому синтаксису размещения.

РЕДАКТИРОВАТЬ: Наряду с пользовательским размещением, новое размещение также помогает повторно инициализировать состояние объекта, как показано ниже.

class Test
{
    int startVal;
public:
    Test()
    {
        startVal = 1;
    }
    void setVal(int val) { startVal = val; }
};
int main()
{
    Test *p = new Test;  //Creates new object and initializes it with
                          //a call to constructor.
    p->setVal(10);  //Change object content.
    new(p) Test; //Reset object:
    //object pointed by p will be re-initialzed here by making
    //a call to constructor. startVal will be back to 1
}

Как описано в комментариях выше, сброс состояния объекта также может быть достигнут с помощью размещения нового. размещение new не выделяет память, оно создает объект по указанному адресу в парантезе.

...