为什么构造函数总是在堆栈上调用?

d3m4nz3

出于某种原因,我决定永远不要在我的程序中使用动态内存分配。这意味着我程序中的所有变量都是静态的,并且从不使用“新”构造函数。但以下代码崩溃,并产生堆栈溢出异常:

VeryLargeObject x; // Global variable -> static memory 

void ResetTheObject() 
{
   x = VeryLargeObject(); 
}

显然,我想要做的就是给 x 一个非常大的对象的默认值,它是一个包含许多不同变量的结构,它们自己的构造函数具有不同的复杂性(所以有很多初始化工作要做)。但是这里语言/编译器已经决定这应该在复制之前发生在堆栈上,并且由于非常大的对象对于堆栈来说太大,我的程序崩溃了。

但是我找到了解决这个问题的方法:

VeryLargeObject x; 

void ResetTheObject() 
{
   new (&x) VeryLargeObject();  
}

我以前从未听说过这个,但它正是我想要的。这是一个“安置新”。它在指针提供的已分配(或简单的静态)内存上调用构造函数。

我的问题,因为我有解决方案,是一个咆哮:为什么这不是第一个代码的默认行为?如果没有更简单的方法来做到这一点(即没有“新”这个词与之有任何关系),那为什么呢?另外为什么它会向我发送指针,即使我刚刚提供了它?我认为 C++ 是一种很棒的语言,但这看起来有点丑陋,而且没有经过深思熟虑。

沙迦·舍梅什

首先,启用优化可能会使用第一种语法获得您想要的结果。没有它,这是您要求编译器执行的操作:

  1. 创建一个类型为 的临时对象VeryLargeObject
  2. 将其分配给名为x.

由于临时对象需要存储,编译器在堆栈上分配它们。从字面上看,编译器所做的就是您要求编译器执行的操作。

如果优化被打开,编译器可以理解序列是什么并保存副本。这要求编译器可以积极地向自己证明旧的值x不会以任何方式妨碍。由于您承认初始化非常复杂,如果编译器没有设法这样做,您可以原谅它。

你有两个选择。您可以创建一个就地初始化函数并调用它而不是构造函数,也可以像您一样使用placement new。

使用 new 放置的危险在于,它替换了旧值而x没有适当地破坏它。它只是假设它x是未初始化的。如果您可以使用它,请继续使用它。就编译器而言,不允许假设这一点。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么总是在__new __()之后调用__init __()?

为什么总是在mouseDoubleClickEvent之前调用mousePressEvent

为什么总是在 blazor 中调用“HandleValidSubmit()”

为什么总是在JavaScript中声明函数?

为什么在类构造函数上调用的方法应该是最终的?

为什么总是说“在调用超类型构造函数之前不能引用名称”

为什么“ resolve”方法总是调用已经在Unity中注册的类构造函数?

C ++为什么在堆栈中构造完对象后立即调用析构函数?

是否总是在主线程上调用SKProductsRequestDelegate方法?

为什么选项的位置总是在变化?

为什么UDPSocket.send总是在Ruby中调用getaddrinfo?

为什么总是在Android中启动JobService()中的onCreate()函数?

为什么状态总是在 Apache Flink 的协进程函数中返回 null?

为什么系统函数总是在C ++中返回转换后的退出状态?

为什么要调用移动构造函数?

为什么未调用move构造函数?

为什么operator *不调用构造函数?

为什么不调用move构造函数

为什么调用父的构造函数

为什么复制构造函数被调用?

为什么要调用构造函数?

为什么复制构造函数被调用?

为什么调用复制构造函数而不是移动构造函数?

为什么调用复制构造函数而不是移动构造函数?

什么时候构造函数调用中的堆栈对象?

为什么“解构函数”调用比“构造函数”调用多?

为什么要在Observable函数上调用.call()?

为什么在渲染上调用我的动作函数?

为什么我需要从另一个来源指向 Array 构造函数,为什么我不能直接在数组对象上调用 toString() ?