C++ 是C++;使用'=';?

C++ 是C++;使用'=';?,c++,struct,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]); } 向量v; 对于(int i=0;i

如果结构被完全复制,那么第一个循环比第二个循环更昂贵,因为它为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]);
}
向量v; 对于(int i=0;i 假设我想编写高效的代码(如循环2所示),但同时我想命名从v中提取的MyStruct元素(如循环1所示)。我可以这样做吗?

当您使用
=
时,结构(以及与此相关的所有变量)确实被完全复制。重载
=
运算符和复制构造函数可以让您更好地控制所发生的事情,但是您无法使用它们将行为从复制更改为引用。您可以通过创建如下引用来解决此问题:

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

void doSomething(const structType& x);

如果
sizeof structType
大于
sizeof structType*
常量
用于防止函数修改参数,模仿传递值行为。

在第一个示例中,对象将被复制,您必须处理复制开销

如果您不希望开销过大,但仍然希望有一个本地对象,那么可以使用引用

for (int i = 0; i < v.size(); ++i) {
    MyStruct& s = v[i];
    doSomething(s);
}
for(int i=0;i
已复制*。除非重载赋值运算符。此外,C++中的结构和类在这方面是相同的,它们的复制行为与C语言中的不同。

如果你想深入C++,你也可以查找移动运算符,但是一般来说最好不要忽视初学者。 C++没有垃圾收集功能,可以更好地控制内存管理。如果您想要类似于c#引用的行为,可以使用指针。如果使用指针,则应将其与智能指针()一起使用

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


附言:根据你问题中的词汇表,我假设你来自c#背景。

你可以使用引用或指针来避免复制和有相关的名称

vector<MyStruct> v;

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

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

例如:

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

  std::vector<int> myVector = std::move(foo());
std::vector foo();//返回一个长向量
std::vector myVector=std::move(foo());
将导致一个移动构造,希望它只是在新的myVector对象中执行非常有效的内存重指向,这意味着您不必复制大量数据


但是,也不要忘记返回值优化。这只是一个微不足道的例子。当可以使用RVO时,它实际上优于移动语义。RVO允许编译器在返回对象时完全避免任何复制或移动,而不是直接在返回对象的堆栈上使用它(请参阅)。根本不调用构造函数。

引用?指针?如果编译器知道复制构造函数是微不足道的(例如,由编译器提供),我打赌它会生成完全相同的程序集,前提是
doSomething
的语义在这两者之间不发生变化。“假设我想写有效的代码”,而
doSomething()
的签名是??这是决定性的一点!未使用赋值运算符。移动赋值运算符也是如此。这里只调用构造函数。T foo=巴;是T foo(bar)的语法糖;关于P.S:事实并非如此。但是,这是一个有趣的读物。我很好奇,你从哪种语言来?那么,彼得C++是我用得更多,知道最好的语言。
vector<MyStruct> v;

for (vector<MyStruct>::iterator it = v.begin(); it != v.end(); ++it) {
    doSomething(*it);
}
  std::vector<int> foo(); // returns a long vector

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