返回c++03与11中的值
Return values in c++03 vs 11
我花了几个小时讨论右值和左值。以下是我对的理解
int main()
{
//.....
Foo foo = Bar1();
foo = Bar2();
//......
}
Foo Bar1()
{
//Do something including create foo
return foo;
}
Foo& Bar2()
{
//Do something including create foo
return foo;
}
在c++03下,Bar1()
会复制返回对象(就在返回之前),然后返回复制对象的地址;执行即将被销毁的对象的浪费性拷贝。Bar2()
将返回在函数中创建的对象。
在c++11下,Bar1()
和Bar2()
本质上是等价的(也等价于c++03的Bar2()
)。
是这样吗?如果没有,请详细说明。
它们不一样。Bar2()
在两个标准中都是UB。不能返回通过引用在堆栈上创建的对象。
在C++03中,Bar1()
可以利用RVO,并且不会复制任何内容。在C++11中,Bar1()
甚至将使用RVO,或者如果RVO不可能,则将使用移动构造函数。
从旧的C++到C++11,右值和左值的概念没有改变。你所描述的"C++03"就是应该发生的事情。在某些情况下,一些编译器优化可以减少不必要的副本数量(包括不必要的复制构造函数调用!),但在其他方面也是如此。
改变的是C++11引入了右值引用(T&&
)的概念。
有几篇文章你可以在谷歌上搜索,例如在这里:
http://thbecker.net/articles/rvalue_references/section_01.html
Bar2()
不会在C++2003或C++2011中创建任何副本。对于Bar1()
,在C++2003和C++2011中都创建了foo
的副本。只有当你确实有一个右值,或者你有一个即将消失的左值,并且它正在被返回时,右值引用的使用才适用。
当然,这个例子恰好是未定义的行为,因为返回的foo
就是初始化的foo
。也就是说,当返回foo
时,您的示例似乎因为没有说明它的含义而变得一团糟。假设每个函数都有一个局部变量foo
,根据这两个标准,Bar2()
是未定义的行为,Bar1()
有些不同:
- 如果
Foo
有移动构造函数,C++2011可以使用移动构造函数,而C++2003可以使用复制构造函数 - 是否使用move构造函数或copy构造函数取决于函数的其余部分和编译器:如果
Bar1()
中的所有return
语句都返回foo
,则大多数编译器将忽略额外对象的构造
Bar2()将返回在函数中创建的对象。
这显然是错误的。Bar2()
将返回对某个对象的引用。(注意:如果对象是在Bar2()
内部的堆栈上创建的,那么它将是UB)。
在c++11下,Bar1()和Bar2()本质上是等价的(也等价于c++03的Bar2(())。
在C++11下,含义相同。你真正感兴趣的是移动语义:
Foo Bar3()
{
//Do something
return std::move(foo);
}
这不会执行复制构造函数,而是执行移动构造函数——这应该不会占用太多资源。
这篇文章对你来说可能很有趣:想要速度?传递值。
在C++03中,Bar1()
可以复制对象(但这是通过所谓的复制省略进行优化的——请参阅链接)。
在C++11中,基本上没有任何变化。编译器可以调用Foo
的复制构造函数或Foo
的移动构造函数,也可以执行复制省略。但是,由于即使在C++03中,副本也会被消除,Bar1()
在C++11和C++03中也会这样做。
Bar2()
只返回一个引用,在C++11中没有什么不同。返回引用可能至关重要。如果foo
将是一个局部值,则返回对已销毁变量的引用,而不是对该变量的引用。
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 什么时候在C++中返回常量引用是个好主意
- 你能重载对象变量名本身返回的内容吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何获取std::result_of函数的返回类型
- QueryWorkingSet总是返回false
- (C++)分析树以计算返回错误值的简单算术表达式
- 访问者访问变体并返回不同类型时出错
- 如何返回一个类的两个对象相加的结果
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- lower_bound()返回最后一个元素
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 如何取消对nullptr的屏蔽,返回正确的对象
- 返回c++03与11中的值
- 为什么将boost::move()的返回值分配给非常数引用在C++0x模式下失败,但在C++03模式下有效
- C++03中的函数返回类型推导
- 如何用C++03中成员函数返回的值填充向量
- c++ 03中模板函数返回类型的推导