第二行是什么? (在回答另一个问题时看到。)
int * x = new int [1] ;
int * y = new (x) int;
在第二行之后,x和y具有相同的值(指向同一位置)。 y = x和第二行之间有什么区别?它是构造函数还是其他东西?
答案 0 :(得分:13)
这是placement new。它在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
答案 1 :(得分:4)
这称为placement new。它允许您在已经分配的内存中构造一个对象。
这个早期的主题讨论where and how it is useful for。
答案 2 :(得分:3)
第二个新内容是“放置新”。它执行初始化(即调用任何必要的构造函数)而不进行任何分配。当您需要创建自定义内存分配方案时,它非常有用。
答案 3 :(得分:3)
这是新的展示位置。
虽然你不喜欢,但通常使用整数类型 它通常用于构建缓冲区,然后在其中构建其他类型。
// 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");
这是基础知识
但请记住,使用delete
语句删除使用展示位置分配的对象 。这是因为delete
尝试回收new
分配的内存(以及调用析构函数)。因此,要正确使用这些对象,必须手动调用析构函数。
t1->~T();
t2->~T();
不要忘记删除原始缓冲区。
delete [] buffer;
其他一些警告:
人们经常看到缓冲区可以在堆栈上实现,因此可以自动释放
char buffer[sizeof(T) * 2];
不幸的是,这在技术上可能是正常的(它编译)。但是不能保证工作,因为缓冲区的内存可能无法正确对齐,以便将T放置在内部。因此,您必须动态分配缓冲区(通过使用新的保证,内存已正确对齐任何分配大小的对象(因此通过扩展,它也可以对齐任何小于分配大小的大小)。简单的方法来绕过这个问题是使用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.
请记住,如果使用重置方法,则必须首先销毁旧对象(否则对象可能无法正常运行)。
答案 4 :(得分:2)
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
}
如上面的评论中所述,也可以使用placement new来实现对象状态重置。 placement new不分配内存,它在paranthesis中的指定地址构造对象。