Что это за второе?
Какая вторая строка? (Видно, отвечая на другой вопрос.)
int * x = new int [1] ;
int * y = new (x) int;
После того, как вторая строка x и y имеют одинаковое значение (указывают на одно и то же место). Какая разница между y = x и второй строкой? Это как конструктор или что-то еще?
Ответы
Ответ 1
Это размещение нового. Он создает новый 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
Ответ 2
Это называется размещение нового. Он позволяет вам создать объект в уже выделенной памяти.
Этот более ранний поток обсуждает где и как это полезно для.
Ответ 3
Второе новое - "новое место размещения". Он выполняет инициализацию (т.е. Вызывает любые необходимые конструкторы) без какого-либо выделения. Это полезно, когда вам нужно создать схему выделения пользовательской памяти.
Ответ 4
Это новое место размещения.
Хотя вы не обычно используете его с целыми типами.
Он обычно используется для создания буфера, в котором вы затем создаете другие типы.
// 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];
К сожалению, это может быть технически нормально (он компилируется). Но не гарантируется работа, так как память буфера может быть не правильно выровнена для размещения Т внутри. Таким образом, вы должны динамически распределять буфер (с помощью новых gurantees, чтобы память была правильно выровнена для любого объекта выделенного размера (таким образом, по расширению он также выравнивается для любого размера, меньшего размера, чем размер, выделенный). Легкий способ обойти эта проблема заключается в использовании 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 - это reset объект.
Я видел это, но я предпочитаю использовать более стандартный оператор присваивания:
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.
Помните, если вы используете метод reset, вы должны сначала уничтожить старый объект (или объект может вести себя неправильно).
Ответ 5
int * y = new (x) int;
Это соответствует новому синтаксису размещения.
EDIT: наряду с пользовательским распределением, размещение new также помогает повторно инициализировать состояние объекта, как показано ниже.
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 не выделяет память, оно строит объект по указанному адресу в паратете.