出于某种原因,我决定永远不要在我的程序中使用动态内存分配。这意味着我程序中的所有变量都是静态的,并且从不使用“新”构造函数。但以下代码崩溃,并产生堆栈溢出异常:
VeryLargeObject x; // Global variable -> static memory
void ResetTheObject()
{
x = VeryLargeObject();
}
显然,我想要做的就是给 x 一个非常大的对象的默认值,它是一个包含许多不同变量的结构,它们自己的构造函数具有不同的复杂性(所以有很多初始化工作要做)。但是这里语言/编译器已经决定这应该在复制之前发生在堆栈上,并且由于非常大的对象对于堆栈来说太大,我的程序崩溃了。
但是我找到了解决这个问题的方法:
VeryLargeObject x;
void ResetTheObject()
{
new (&x) VeryLargeObject();
}
我以前从未听说过这个,但它正是我想要的。这是一个“安置新”。它在指针提供的已分配(或简单的静态)内存上调用构造函数。
我的问题,因为我有解决方案,是一个咆哮:为什么这不是第一个代码的默认行为?如果没有更简单的方法来做到这一点(即没有“新”这个词与之有任何关系),那为什么呢?另外为什么它会向我发送指针,即使我刚刚提供了它?我认为 C++ 是一种很棒的语言,但这看起来有点丑陋,而且没有经过深思熟虑。
首先,启用优化可能会使用第一种语法获得您想要的结果。没有它,这是您要求编译器执行的操作:
VeryLargeObject
。x
.由于临时对象需要存储,编译器在堆栈上分配它们。从字面上看,编译器所做的就是您要求编译器执行的操作。
如果优化被打开,编译器可以理解序列是什么并保存副本。这要求编译器可以积极地向自己证明旧的值x
不会以任何方式妨碍。由于您承认初始化非常复杂,如果编译器没有设法这样做,您可以原谅它。
你有两个选择。您可以创建一个就地初始化函数并调用它而不是构造函数,也可以像您一样使用placement new。
使用 new 放置的危险在于,它替换了旧值而x
没有适当地破坏它。它只是假设它x
是未初始化的。如果您可以使用它,请继续使用它。就编译器而言,不允许假设这一点。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句