C++ 为什么总是在堆栈上调用构造函数?
出于某种原因,我决定在我的程序中永远不要使用动态内存分配。这意味着我的程序中的所有变量都是静态的,并且从不使用“new”构造函数。但以下代码崩溃,并产生堆栈溢出异常:C++ 为什么总是在堆栈上调用构造函数?,c++,C++,出于某种原因,我决定在我的程序中永远不要使用动态内存分配。这意味着我的程序中的所有变量都是静态的,并且从不使用“new”构造函数。但以下代码崩溃,并产生堆栈溢出异常: VeryLargeObject x; // Global variable -> static memory void ResetTheObject() { x = VeryLargeObject(); } 显然,我要做的就是给x一个VeryLargeObject的默认值,它是一个包含许多不同变量的结构,它们
VeryLargeObject x; // Global variable -> static memory
void ResetTheObject()
{
x = VeryLargeObject();
}
显然,我要做的就是给x一个VeryLargeObject的默认值,它是一个包含许多不同变量的结构,它们自己的构造函数具有不同的复杂性(因此有相当多的初始化工作要做)。但是在这里,语言/编译器决定在复制之前应该在堆栈上执行此操作,并且由于VeryLargeObject对于堆栈来说太大,因此我的程序崩溃
然而,我找到了这个问题的解决方案:
VeryLargeObject x;
void ResetTheObject()
{
new (&x) VeryLargeObject();
}
我以前从未听说过这个,但它正是我想要的。这是一个“新的安置”。它在指针提供的已分配(或只是静态)内存上调用构造函数
既然我有了解决方案,我的问题就是:为什么这不是第一个代码的默认行为?如果没有一种不那么老套的方法来做这件事(即没有“新”这个词),那为什么呢?还有,为什么它会将指针发回给我,即使我只是提供了它?我认为C++是一门很棒的语言,但这看起来有点丑陋,而且没有很好的思考。p> 首先,启用优化可能会让您获得第一种语法所需的功能。如果没有它,以下是您要求编译器执行的操作:
VeryLargeObject
的临时对象x
的全局变量中x
的旧值不会以任何方式妨碍编译。既然您承认初始化相当复杂,那么如果编译器没有做到这一点,您可以原谅它
你有两个选择。您可以创建一个就地初始化函数并调用它而不是构造函数,也可以像以前一样使用placement new
使用“新位置”(placement new)的危险在于,它会替换
x
的旧值,而不会对其进行适当的破坏。它只是假设x
未初始化。如果你可以用,那就用吧。编译器不允许假设,“由于某种原因,我决定在程序中永远不使用动态内存分配”。“我认为C++是一种很好的语言,但是这看起来有点丑陋,而且没有很好的考虑。”你看不到连接是否是BTW?“这意味着我的程序中的所有变量都是静态的”,不是。这并不意味着。你真的不想要一堆全局变量。你不能用这种方式使用新的布局。您首先需要通过调用原始对象的析构函数来销毁它。VeryLargeObject
是否遵循5的规则?它有一个移动构造函数和一个移动赋值操作符吗?“我认为C++是一种很棒的语言,但是这看起来有点丑陋,而且没有很好的考虑。”我觉得奇怪的是,这个特殊的东西是C++中难看的东西。如果代码> x>代码>是POD,那就行了。最安全的方法是在执行新的放置之前只调用旧实例上的析构函数。如果是吊舱,无论如何,析构函数可能是一个空操作。如果不是,你会很高兴你叫它。我想太优化可能会有帮助,但我从O2切换到O4,它是一样的。事实上,VeryLargeObject有大量的对象需要初始化,而编译器只是懒得检查优化过程中是否有任何障碍。