基本的RValue方法返回
Basic RValue method return
假设一个基本方法:
std::string StringTest()
{
std::string hello_world("Testing...");
return std::move(hello_world);
}
我应该如何使用输出:
选项:
auto& string_test_output=StringTest();
选项B:
auto string_test_output=StringTest();
StringTest()是一个临时值吗?如果是这样,选项A就不安全了。如果它不是一个临时值,我觉得选项B会导致复制。
我仍然习惯使用RValue引用,所以按值返回仍然是非常可怕的,因为我不希望发生复制或遇到不必要的复制!
最好的方法是这样修改你的方法:
std::string StringTest()
{
std::string hello_world("Testing...");
return hello_world;
}
没有必要告诉函数返回的对象应该是右值,这是由于该值是临时的而自动产生的——也就是说,它在调用处没有绑定到任何名称。因此,初始化的will值已经被移动构造(除非函数内部的临时变量被完全省略),不需要您手动表达这样的意图。
另外,由于您的返回类型是std::string
,因此您将按值返回,而不是按右值引用返回,因此在返回之前没有必要移动返回参数。实际上,调用std::move
除了可能欺骗编译器在返回值之前执行额外的不必要的move-构造函数之外,不会有任何效果。这样的技巧除了使您的代码稍微复杂一些,并且可能运行得更慢之外,没有任何作用。
你也想按值返回。其中一个原因是由于回报价值优化(RVO)。大多数编译器都会这样做,这意味着你最好只是返回一个被省略的"副本",而不是试图聪明地返回一个引用。
即使不能应用RVO,通过右值引用返回它仍然不会改变它的返回方式。当返回值时,由于它在调用位置是临时的,因此返回值将已经是一个右值,可以通过右值引用传递给任何需要它作为参数的函数。例如,如果您使用返回值来初始化一个变量,并且返回值没有被省略,则仍然调用move构造函数(如果可用)。因此,简单地按值返回不会损失太多。
在这种情况下,您可能应该执行以下操作之一来捕获值:
auto string_test_output = StringTest();
std::string string_test_output = StringTest();
按值返回std::string(以及一般情况下,任何可移动类型),因此初始化新对象永远不会触发复制构造。在最坏的情况下,它将触发move构造,但通常由于复制省略,不会涉及运行时开销。
我推荐这篇文章来了解值语义及其成本的背景知识。
- 从父类方法返回子类对象
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 让bool方法返回其他整数
- 不能将方法返回的值用于另一个方法
- 从私有成员变量的成员方法返回unique_ptr
- 我的模板类方法返回错误类型?
- QtQuick - qml:28:错误:未知方法返回类型:自定义类型
- 我无法使用C++指针指向类方法返回的 std::vector
- 对象引用中的字段以不同的方法返回不同的值
- 类方法返回指向具有模板的类成员的指针
- 如何将字符串从 C++/CLI 方法返回到调用它的非托管C++
- 从工厂方法返回的ComPtr的引用计数增加两次
- 如何使用 SFINAE 从 end() 方法返回 (const_) 迭代器
- Arduino trim() 和 replace() 方法返回从 'void' 到非标量类型'String'请求的转换
- 从类方法返回 "const char*" 作为 std::string&
- 如何使用 "get" 方法返回类的私有 std::unique_ptr 成员
- 可能从单个方法返回不同类型的对象
- qml 未知方法返回类型:ArchiveFile*,即使调用了 qmlRegisterUncreatableType
- 如何从方法返回静态常量 int std::array?
- 当从其他方法返回 vector 时,C++无法访问矢量元素