将值从本地堆栈移动到堆?(C++)

non*_*ot1 25 c++ heap stack

如何从方法调用中获取对象值作为结果并将其放在堆上?

例如:

Qt QImage::scaledToWidth方法返回QImage对象的副本.

现在我正在做:

QImage *new_img_on_heap = new QImage(old_imgage_on_heap->scaledToWidth(2000));
Run Code Online (Sandbox Code Playgroud)

这是唯一的方法吗?看起来它已经经历了制作第三个全新物体的麻烦,当我已经在堆栈上有一个完美的好物品时.

我想把它放在堆上的原因是因为真实QImage的很大,我希望它比当前方法的生命周期更长.我打算在我班上的一个字段中填充指针.

我知道QImage有一些隐含的数据共享,但我并不清楚它是如何工作的.另外,我想知道一个通​​用的解决方案,如果我需要使用不像Qt那样精心设计的对象.

Jam*_*nze 15

对象由其地址标识.如果你想在另一个地址,你必须构建一个新地址; 你无法移动物体.(即使使用C++ 11,新的"移动"语义实际上并不会移动对象;如果您知道自己不需要移动它的值,它们会提供一种优化的移动值的方法.)

  • +1:注意与对象和值的区别,以及*move-constructor*和*move-assignment*不*移动*对象,只有内容可以移动的事实*非常重要*并不总是) (2认同)

spr*_*aff 5

首先,在大多数情况下,您应该更喜欢堆栈.

其次,当您在堆上分配对象时,您应该将原始指针包装在堆栈中的某个托管对象中.如果没有别的,请为异常安全做.

第三,Qt的对象通常做到这点即有写作没有优势new QImagenew QMap<int>等.

然而,将非堆对象移动到堆上的正确方法就是说

new ObjectType (old_instance)
Run Code Online (Sandbox Code Playgroud)

如果使用临时对象执行此操作,例如

new ObjectType (create_object ())
Run Code Online (Sandbox Code Playgroud)

然后它可能会删除额外的副本(链接为我打破 - 缓存)

  • @spraff:我已经回到了基础并阅读了调用约定,这是我之前应该做的事情.在32位和64位,Microsoft和GCC中按值返回的调用约定不使用对象的固定位置(我错误地认为),而是将指针传递给要返回的对象的位置(除非它适合寄存器),这意味着对象可以位于任何地方.我错误地认为返回的对象(对于大型对象)必须在堆栈中进行布局.+1 (4认同)
  • 堆栈和堆(或者更准确地说是自动与动态存储)的决定应该与对象生存期相关,而不是与对象的大小相关.如果QImage要比当前上下文更长,则在当前范围内不能具有自动存储持续时间. (3认同)
  • *足够大*对于没有经验的程序员来说实际上是很难识别的。std :: vector &lt;int&gt;是否包含10个*足够大*的元素?那100.000.000个元素呢?还是向量中的元素数量根本不重要?那么,来自一个18M像素相机的QImage呢,是否足够大以至于必须使用动态内存?所存储图像的大小实际上是否重要? (2认同)