如何从方法调用中获取对象值作为结果并将其放在堆上?
例如:
Qt QImage::scaledToWidth
method返回QImage
对象的副本。
现在我正在做:
QImage *new_img_on_heap = new QImage(old_imgage_on_heap->scaledToWidth(2000));
这是唯一的方法吗?好像它已经经历了制作第三个全新物体的麻烦,当我已经在堆栈上有一个完美的好物品时。
我想把它放在堆上的原因是真正的QImage
很大,我希望它比当前方法的生命周期更长。我本打算在我班上的一个字段中填充指针。
我知道QImage
有一些隐含的数据共享,但我并不清楚它是如何工作的。另外,我想知道一个通用的解决方案,如果我需要使用不像Qt那样精心设计的对象。
答案 0 :(得分:14)
对象由其地址标识。如果你想要它在另一个 地址,你必须建立一个新的;你无法移动物体。 (甚至 使用C ++ 11,新的“移动”语义实际上并没有移动 宾语;如果你知道的话,它们提供了一种优化的价值转移方式 您不需要移动它的值。)
答案 1 :(得分:5)
首先,在大多数情况下,您应该更喜欢堆栈到堆中。
其次,当您在堆上分配对象时,您应该将原始指针包装在堆栈中的某个托管对象中。如果没有别的,请为异常安全而做。
第三,Qt对象通常是do exactly that,即写new QImage
或new QMap<int>
等没有优势。
然而,将非堆对象移动到堆上的正确方法是
new ObjectType (old_instance)
如果使用临时对象执行此操作,例如
new ObjectType (create_object ())
然后它可能会elide the extra copy(链接打破我 - cached)
答案 2 :(得分:0)
自方法
QImage QImage :: scaledToWidth(int width,Qt :: TransformationMode mode = Qt :: FastTransformation)const
不会返回QImage地址(即QImage&amp; ....),而不是我认为你运气不好。你被困在一个副本。除非您想重新编译QT库以更改该功能签名,否则它不会返回副本。
将这个对象放在堆栈上有什么不好呢?
答案 3 :(得分:0)
您可以尝试以下技巧。想法是将您的价值放在一些结构上并在堆中构造结构。在这种情况下,复制省略有效。不执行任何复制或移动。不幸的是,它不适用于VS2017。但它可以在G ++ 8+和VS2019中使用。
#include <memory>
struct C{
C() = default;
C( C&& ) = delete;
C( C const& ) = delete;
C& operator=( C&& ) = delete;
C& operator=( C const& ) = delete;
};
C foo() {
return C {};
}
struct X {
C c;
X()
: c (foo()) // here is how trick works
{
}
};
int main() {
auto x = std::make_unique<X>();
}
答案 4 :(得分:0)
这个问题/询问的前提是错误的,因为它假定QImage的图像数据具有与QImage对象本身相同的生存期。
我想将其放在堆上的原因是因为实际的QImage很大,并且我希望它比当前方法的生存期更长。我打算在班级的某个字段中塞满指向它的指针。
该语句是不正确的,因为对于QImage之类的东西,这将是非常糟糕的事情,并且由于弹出“堆栈”限制而很快失败。这也会使作业非常慢!
相反,QImage像许多处理大型和/或外部数据的C ++对象一样,实际上是围绕不同生命周期的内部托管内存的<包装> 包装>。可以在the QImage source code中看到; QImage包含QImageData,而QImageData malloc的内部缓冲区独立于原始QImage的生存期。
由于大部分数据都位于QImage的“外部”,因此没有充分的理由偏爱new QImage
而不是使用QImage
和自动生存期,这是因为(图像数据; QImage明智地实现了复制和移动*,以便共享所有基础图像数据(以及此类图像的基础分配)。
*在QImage's copy ctor中,QImageData的“引用计数”被短暂地扩展,直到前一个对象被销毁为止,而在移动过程中,QImageData的生存期可以被直接转移(注释中,该源缺少了吗?) 。无论如何,这两种情况都不会真正复制基础图像数据,而这会很昂贵。
因此,要回答以下问题:new X(non_ptr_X)
,并让编写正确的构造函数/设计完成工作,这是实现的细节;并希望是令人满意的性能特征之一。 YMMV。