C ++结构是完全复制还是仅在使用'='时引用?

时间:2014-02-10 02:36:24

标签: c++ struct

如果结构被完全复制,那么第一个循环比第二个循环更昂贵,因为它正在为v的每个元素执行一个额外的副本。

vector<MyStruct> v;

for (int i = 0; i < v.size(); ++i) {
    MyStruct s = v[i];
    doSomething(s);
}

for (int i = 0; i < v.size(); ++i) {
    doSomething(v[i]);
}

假设我想编写有效的代码(如在循环2中),但同时我想命名从v中绘制的 MyStruct 元素(如在循环1中)。我能这样做吗?

5 个答案:

答案 0 :(得分:6)

当您使用=时,确实完全复制了结构(以及所有变量)。重载=运算符和复制构造函数可以让您更好地控制发生的情况,但是您无法使用这些操作来更改从复制到引用的行为。您可以通过创建这样的引用来解决此问题:

for (int i = 0; i < v.size(); ++i) {
    MyStruct& s = v[i]; //& creates reference; no copying performed
    doSomething(s);
}

请注意,除非将参数声明为引用,否则在将结构传递给函数时仍将完全复制该结构。将结构作为参数时,这是一种常见的模式。例如,

void doSomething(structType x);

通常会比

更差
void doSomething(const structType& x);

const用于防止函数修改参数,模仿按值传递行为。

答案 1 :(得分:3)

在您的第一个示例中,对象将被复制,您将不得不处理副本开销的成本。

如果您不想要头顶的费用,但仍想拥有本地对象,那么您可以使用引用。

for (int i = 0; i < v.size(); ++i) {
    MyStruct& s = v[i];
    doSomething(s);
}

答案 2 :(得分:2)

复制*。除非您重载赋值运算符。此外,C ++中的Structs和Classes在这方面是相同的,它们的复制行为与c#中没有区别。

如果你想深入研究C ++,你也可以查找移动运算符,但通常最好忽略它对于初学者。

C ++没有垃圾收集,并且可以更好地控制内存管理。如果你想要类似于c#引用的行为,你可以使用指针。如果使用指针,则应将它们与智能指针(What is a smart pointer and when should I use one?)一起使用。

*请记住,如果struct存储指针,复制结构中的指针将指向同一位置。如果该位置中的对象发生更改,则两个结构的指针都将看到更改的对象。

P.S:我假设你来自c#背景,基于你问题中的词汇。

答案 3 :(得分:2)

您可以使用引用或指针来避免复制并具有与之相关的名称。

vector<MyStruct> v;

for (int i = 0; i < v.size(); ++i) {
    MyStruct& s = v[i];
    doSomething(s);
}

但是,由于您为容器使用了向量,因此使用迭代器可能是个好主意。 doSomething应该通过const ref进行参数,否则,你仍然会复制以将参数传递给它。

vector<MyStruct> v;

for (vector<MyStruct>::iterator it = v.begin(); it != v.end(); ++it) {
    doSomething(*it);
}

答案 4 :(得分:2)

在您的示例中,您正在创建副本。但是,并非所有使用operator'='都会产生副本。 C ++ 11允许“移动构造”或“移动分配”,在这种情况下,您实际上并不是在复制数据;相反,你只是(希望)从一个结构到另一个结构的高速移动。 (当然,它实际上做的完全取决于如何实现移动构造函数或移动赋值运算符,但这是意图。)

例如:

  std::vector<int> foo(); // returns a long vector

  std::vector<int> myVector = std::move(foo());

将导致MOVE构造,希望只是在新的myVector对象中执行非常高效的内存重定位,这意味着您不必复制大量数据。

不要忘记返回值优化。这只是一个微不足道的例子。 RVO在使用时实际上优于移动语义。 RVO允许编译器在返回对象时简单地避免任何复制或移动,而只是直接在返回它的堆栈上使用它(参见http://en.wikipedia.org/wiki/Return_value_optimization)。根本没有调用构造函数。

相关问题