C++ 关于C++; std::vector func(int num){ std::vec; 整数和=0; for(int i=0;i
下面关于使用右值和左值引用的代码之间有什么区别C++ 关于C++; std::vector func(int num){ std::vec; 整数和=0; for(int i=0;i,c++,c++11,c++14,C++,C++11,C++14,下面关于使用右值和左值引用的代码之间有什么区别 std::vector<std::string> func(int num) { std::vector<std::string> vec; int sum = 0; for(int i = 0; i < num; i++) { sum +=i; std::string s = std::to_string(sum); vec.emplace_back(s); } retur
std::vector<std::string> func(int num) {
std::vector<std::string> vec;
int sum = 0;
for(int i = 0; i < num; i++) {
sum +=i;
std::string s = std::to_string(sum);
vec.emplace_back(s);
}
return vec;
}
std::vector res=func(10);//(案例1)
std::vector&&res=func(10);//(案例2)
std::vector&res=func(10);//我犯了个错误!,案例3
常数std::vector&res=func(10);//案例4
问题:
一起工作(案例4)
常量
左值引用不会延长prvalue的生存期res
是一个自动变量,则两者实际上是相同的。我建议写案例1,因为它更简单,也更容易混淆
首先,从vec
移动到返回值。实际上,乐观主义者可以忽略这一举措。这种优化称为NRVO(称为返回值优化)
从C++17开始:在这两种情况下,都是通过上面提到的移动(可能已经省略)直接初始化的
C++17之前的版本:在这两种情况下,从返回值到初始化对象还有另一个移动。这一举措在实践中也可以省略
因为对非常量的左值引用可能不受右值的约束。在回答您的问题2时:谢谢您的明确回答!那么右值ref返回类型呢?比如:std::vector&&func(int-num){return std::move(vec);}案例2之间的区别是什么?@eerorika我读了很多遍,但我认为你对“内存拷贝”的理解是正确的。是的,它保存内存中的“副本”。不,它不能保存一个额外的副本到新的内存中。@DrewDormann哦,我想我明白你是如何解释这个问题的了。是的,很不清楚。“than case1”让我相信问题在于case2是否避免了case1所拥有的副本。@Andy rvalue ref返回类型不是prvalue,因此在任何情况下都不会发生生存期延长。这个生命周期延长只适用于prvalues。@DrewDormann很抱歉写得不好,我以前甚至不知道prvalue和xrvalue这两个术语,已经学会了!谢谢你的详细回复!对于c++17,你是说它是完美的,比如说编译器只使用扩展到func之外的函数范围中的内存,没有复制或移动?@Andy如果NRVO是为了摆脱第一步,那么就不会有任何移动。我知道了,非常感谢你的详细回答!
std::vector<std::string> res = func(10); // (case 1)
std::vector<std::string> &&res = func(10); // (case 2)
std::vector<std::string> &res = func(10); // I got an error!, case3
const std::vector<std::string> &res = func(10); // case4