【发布时间】:2017-01-19 11:28:40
【问题描述】:
我正在调查从右值引用限定符函数返回右值引用是否真的是个好主意。假设我们有:
class DataPack {
public:
std::vector<int> data;
DataPack(std::initializer_list<int> d) : data{d} {}
std::vector<int>& get_data() & {
return data;
}
std::vector<int>&& get_data() && {
return std::move(data);
}
// This version fixes for-loop problem (see below)
//std::vector<int> get_data() && {
// return data;
//}
};
如果我想在不做临时的情况下获取数据,我可以使用以下方法:
auto my_data = DataPack{1,2,3}.get_data();
但假设我想使用以下代码:
for (auto v : DataPack{1,2,3}.get_data()) {
std::cout << v << ", ";
}
现在这是 UB,因为 get_data() 返回对在完整语句后销毁的临时引用。
也许对于这样的 for - 循环可以以某种方式解决这个问题?或者也许我们应该按价值返回并希望 RVO 能按预期工作?因为上面的内容在我看来不是很安全。
【问题讨论】:
-
为什么一开始还有
get_data()?只需使用data就足够了。但是,是的,您希望按值返回。 -
我看不到 UB。谁能举出为什么这是UB?
DataPack实际上并没有被移出。 -
@FrançoisAndrieux :在内部
for使用auto&&捕获范围表达式,因此它变成auto&& __expr = DataPack{1,2,3}.get_data()。问题是在这个表达式的末尾DataPack被销毁了,所以__expr变成了一个悬空引用。 -
@ildjarn 对,现在看起来很明显。谢谢你的澄清。
-
@T.C.我正在阅读 Scot Meyers Effective Modern C++ 的第 12 项,并且有一个类似于上述示例的示例。我试图找到如何在我的代码中使用 ref-qualifiers,实际上我现在看不到很多用途。即使在 gcc6.3 中,我也只能在可选标头中看到 ref-qualifiers 的使用,它们都返回 constexpr 右值引用。