了解引用绑定
Understanding reference binding
我们不能将非 const 左值引用绑定到右值,但它可以绑定到 const 引用。我们也不能将右值引用绑定到左值。实际上标准是这样说的:
8.5.3/5.2:
the reference shall be an lvalue reference to a non-volatile const
type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.
但是有比"The Standard say so"更好的解释吗?
因为它没有语义意义。
您不能将非常量左值引用绑定到右值,因为修改右值意味着什么?根据定义,没有其他人会看到结果,所以这没有意义。
int& i = 3;
//should change referenced location, but we aren't referencing a memory location
i = 5;
您不能将右值引用绑定到左值,因为右值引用的存在是为了促进对其引用的破坏性优化。你不希望你的物体被任意从你下面移出,所以标准不允许它。
void process_string (std::string&&);
std::string foo = "foo";
//foo could be made garbage without us knowing about it
process_string (foo);
//this is fine
process_string (std::move(foo));
想一些真实的案例:
#include <vector>
void f1( int& i ){i = 1;}
void f2( const int& i ){i = 1;}
void f3( std::vector<int>&& v ){auto v_move{v};}
int main()
{
f1(3); // error: how can you set the value of "3" to "1"?
f2(3); // ok, the compiler extend the life of the rvalue "into" f2
std::vector<int> v{10};
f3(v); // error: an innocent looking call to f3 would let your v very different from what you would imagine
f3(std::vector<int>{10}); // ok, nobody cares if the rvalue passed as an argument get modified
}
我们不能将非 const 左值引用绑定到右值,但它可以绑定到 const 引用。我们也不能将右值引用绑定到左值。实际上标准是这样说的:
8.5.3/5.2:
the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.
但是有比"The Standard say so"更好的解释吗?
因为它没有语义意义。
您不能将非常量左值引用绑定到右值,因为修改右值意味着什么?根据定义,没有其他人会看到结果,所以这没有意义。
int& i = 3;
//should change referenced location, but we aren't referencing a memory location
i = 5;
您不能将右值引用绑定到左值,因为右值引用的存在是为了促进对其引用的破坏性优化。你不希望你的物体被任意从你下面移出,所以标准不允许它。
void process_string (std::string&&);
std::string foo = "foo";
//foo could be made garbage without us knowing about it
process_string (foo);
//this is fine
process_string (std::move(foo));
想一些真实的案例:
#include <vector>
void f1( int& i ){i = 1;}
void f2( const int& i ){i = 1;}
void f3( std::vector<int>&& v ){auto v_move{v};}
int main()
{
f1(3); // error: how can you set the value of "3" to "1"?
f2(3); // ok, the compiler extend the life of the rvalue "into" f2
std::vector<int> v{10};
f3(v); // error: an innocent looking call to f3 would let your v very different from what you would imagine
f3(std::vector<int>{10}); // ok, nobody cares if the rvalue passed as an argument get modified
}