以下示例代码编译.
#define USE_RVALUE // line 1
template<class data_type>
class Container
{
data_type& data;
public:
#ifdef USE_RVALUE
Container(data_type&& _data) : data(_data) {}
#endif
Container(data_type& _data) : data(_data) {}
};
int main()
{
double d = 42.0;
Container<double> c1(d);
Container<double> c2(1.0f); // line 18
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的编译命令:
g++ -std=c++11 -Wall ref.cpp -o ref # g++ is 4.7.1
Run Code Online (Sandbox Code Playgroud)
如果我们退出第1行,g ++会抱怨:
no matching function for call to ‘Container<double>::Container(float)’
ref.cpp:18:34: note: candidates are:
ref.cpp:11:9: note: Container<data_type>::Container(data_type&) [with data_type = double]
ref.cpp:11:9: note: no known conversion for argument 1 from ‘float’ to ‘double&’
[... (more candidates)]
Run Code Online (Sandbox Code Playgroud)
当然,错误是明确的,并且C++ 03中的典型错误:如果这些rvalues不是const,则不允许来自rvalues的引用.但为什么它适用于rvalue构造函数(即#ifdef启用)?我们在初始化列表中具有相同的情况:来自非const值的引用.
另外,如果你解释一下......这段代码是"良好的编码风格"还是"避免"?
答案很简单:无论名称是什么 - 它都是左值.因此,在你的ctor中,使用rvalue引用,_data是ctor体中的左值,尽管它是外部世界中的右值.所以最后你有一个悬空参考,所以你不应该做这样的事情.
基本上,当你接受某些东西时&&(除非在模板中,也就是通用引用),你应该将其视为"这个值将被破坏".因此,您应该从中窃取,更改它,无论如何(除非将其置于某种无效状态,以防止其正常销毁).但是你永远不应该存储指针或引用.因为这个对象可能在你的功能完成后被销毁.这是你的情况.double(1.0f)仅存在于你的ctor体中,并且在它之外没有任何意义,你仍然存储对它的引用.
| 归档时间: |
|
| 查看次数: |
288 次 |
| 最近记录: |