按价值:
class Test {
private:
HugeObject h; // Copy 1
public:
void SetObject(HugeObject hugeObject) { // Copy 2
h = hugeObject; // Copy 3
}
}
// Somewhere else
Test t();
t.SetObject(HugeObject());
这很糟糕,因为会创建三个隐式副本。如果我将SetObject()
的参数更改为const HugeObject& hugeObject
,那么它也很糟糕,因为我会存储在该函数范围之外不再存在的内容。
因此,为防止复制两次并存储无效数据,我只能复制两次:
void SetObject(const HugeObject& hugeObject) {
h = HugeObject(hugeObject); // Copy constructor
}
这是处理这种情况的有效方法还是我误解了什么?愚蠢的优化还是不优化?除了存储指针外还有更好的方法吗?
答案 0 :(得分:1)
这很糟糕,因为会创建三个隐式副本。
实际上,在这种情况下只会发生一个副本。 HugeObject()
临时值作为参数hugeObject
就地构建,然后从那里复制到h
。
如果我将SetObject()的参数更改为
const HugeObject& hugeObject
,那么它也很糟糕,因为我会存储在该函数范围之外不再存在的内容。< / p>
这也不准确 - 你还在复制到h
,你没有存储对它的引用。在以下情况下,这样可以保存一份副本:
HugeObject h;
t.SetObject(h); // copy from h into t.h, no copy necessary
// into the argument of SetObject()
hugeObject
按const&
是在C ++ 03中完成此操作的最佳方法。如果您可以访问C ++ 11编译器,并且HugeObject
可以有效地移动,那么您还应该添加rvalue重载:
void setObject(HugeObject&& hugeObject) {
h = std::move(hugeObject);
}
答案 1 :(得分:1)
为什么不在施工期间拿到物体?然后你得到原创作品和副本。
#include <iostream>
using std::cout;
class Huge
{
public:
Huge() { cout << "constructor\n"; }
Huge(const Huge & h) { cout << "copy\n"; }
Huge & operator = (const Huge & h) { cout << "assignment\n"; return *this; }
};
class Holder
{
Huge h;
public:
Holder(const Huge & h_) : h(h_) {};
};
int main()
{
Huge bar;
Holder foo(bar);
}
输出:
constructor
copy
答案 2 :(得分:1)
当您在课程中首先声明h
时,您实际在做的是调用对象的默认构造函数,这是在创建一个没有使用显式语法的对象;就是这样,
HugeObject h; // Calls default constructor implicitly.
HugeObject h2 = HugeObject(); // Still calls default constructor.
HugeObject ougeHobject = HugeObject(h); // Calls copy constructor.
h2 = ougeHobject; // calls HugeObject's operator=
最后一部分是我真正想到的。当您在h
中将hugeObject
分配给SetObject
时,您实际上正在使用HugeObject
&#39; s operator=
。这不与构造相同。如果operator=
不是由类定义的,那么C ++实现会合成它;此默认值的工作原理是将基本类型(例如double
)的右侧对象的每个成员分配给左侧对象上的相应成员。对于存储为hugeObject,
变量的类类型,将调用其对应的operator=
。
要立即直接回答此问题,如果您要限制所制作的副本,只需将h分配给hugeObject
中的SetObject
引用,因为两者都已实例化:
void SetObject(const HugeObject& hugeObject) {
h = hugeObject;
}
虽然技术上超出了范围,但const HugeObject&
的值会通过HugeObject
&n; operator=
复制到h
。这不会隐式构造一个新对象,因为它们都已经实例化了;再次,它只是调用operator=
。