【发布时间】:2018-07-04 12:53:30
【问题描述】:
我正在将函数的某些返回值绑定到 const 左值引用,但在 const 左值引用的生命周期结束之前,该对象已被删除。
在以下示例中,Foo 对象在 foo 的生命周期结束之前被销毁:
#include <iostream>
#include <string>
struct Foo
{
~Foo()
{
std::cout << "Foo destroyed: " << name << std::endl;
}
std::string name;
};
Foo&& pass_through(Foo&& foo)
{
return std::move(foo);
}
int main()
{
const Foo& foo = pass_through({"some string"});
std::cout << "before scope end" << std::endl;
}
输出是:
Foo 被破坏:一些字符串
在范围结束之前
住在科里鲁:1
我认为你可以将const T& 绑定到任何东西。返回T&& 是不好的做法吗?应该首选按值返回吗?
我在这里的 cpprestsdk 中偶然发现了这个:
inline utility::string_t&& to_string_t(std::string &&s) { return std::move(s); }
https://github.com/Microsoft/cpprestsdk/blob/master/Release/include/cpprest/asyncrt_utils.h#L109
非常混乱,因为 to_string_t 的 windows 版本(由预处理器宏调度)按值返回:
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string &&s);
编辑:
为什么将pass_through 的结果传递给采用const Foo& 的函数时会起作用?这种情况下寿命会延长吗?
【问题讨论】:
-
一大早来不及思考,但显式析构函数可能会阻止隐式创建移动构造函数。 en.cppreference.com/w/cpp/language/move_constructor
-
仅当引用直接绑定到临时对象时才适用生命周期延长。
-
@KennyOstrom 我尝试通过
Foo(Foo&&) = default;显式生成默认移动构造函数,它产生了相同的结果。 -
您可以将它作为参数传递,因为临时的生命周期持续到创建它的“完整表达式”结束。(非常非正式地,“直到下一个分号”。)没有扩展是必要的。
-
静态分析应该能够检测到这一点,我预测我们将来会看到编译器能够对此发出警告
标签: c++ c++11 move-semantics