第二行是什么?(在回答另一个问题时看到。)
int * x = new int [1] ;
int * y = new (x) int;
第二行代码执行后,x和y将拥有相同的值(指向同一个位置)。那么y = x和这段代码的区别是什么?这像是一种构造函数还是其他什么东西吗?
第二行是什么?(在回答另一个问题时看到。)
int * x = new int [1] ;
int * y = new (x) int;
第二行代码执行后,x和y将拥有相同的值(指向同一个位置)。那么y = x和这段代码的区别是什么?这像是一种构造函数还是其他什么东西吗?
这是 定位 new。 它在指向 x
的内存中构造一个新的 int
。
如果你尝试:
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
new(x) int
!= new(x) int()
! - Roger Patex
处的内存。”因此,它不会修改x
,而是覆盖了你在第一行创建的int
。 - Jonathan Grynspany
指向与x
相同的内存地址。可以将其视为省略了内存分配步骤,直接使用提供的内存块立即执行适当的构造函数调用。 - Péter Törökint
类型,在这种情况下没有太大的区别。然而,对于非原始类型,可能会有很大的区别。例如,您可以分配一个适当大小的char
数组,然后使用放置new将一个YourFavouriteType
对象初始化到其中。然后,您就有了一个指向物理上相同内存的char*
和YourFavouriteType*
,但是它们“看到”的可能是非常不同的东西。 - Péter Török// 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];
很遗憾,这在技术上可能是可以的(它可以编译)。但不能保证缓冲区的内存正确对齐以便于放置T。所以你必须动态分配缓冲区(通过使用new,它保证了为分配大小的任何对象正确对齐的内存(因此按扩展也对分配大小小于分配大小的任何对象正确对齐)。解决此问题的简单方法是使用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.
请记住,如果您使用重置方法,必须先销毁旧对象(否则对象可能无法正确运行)。
int * y = new (x) int;
这是使用放置new语法实现的。
编辑:除了自定义分配,放置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(x) int()
会有所不同,但可以通过模板使用。即使是在使用 new[] 时,始终使用括号也是一个好习惯。 - Roger Pate