右值引用可以作为 const 引用传递吗?
Can rvalue references be passed on as const references?
考虑以下示例 struct
:
struct A {
int i;
void init(const A &a)
{
this->i = a.i;
}
A(int i)
{
this->i = i;
}
A(const A &a) = delete;
A &operator=(const A &a) = delete;
A(A &&a)
{
init(a); // Is this allowed?
}
A &operator=(A &&a)
{
init(a); // Is this allowed?
return *this;
}
};
右值引用 A &&a
被传递给接受 const A &a
的函数,即常量左值引用。这是否允许并导致 C++ 中明确定义的行为?
是的,允许。
注意,表达式 a
的值类别是左值,即使 a
声明的类型是右值引用。
此外,如果您使用 std::move
从 a
创建右值,您的代码仍然是格式正确的,因为右值可以绑定到 const 左值引用:
init(std::move(a)); // std::move(a) is an rvalue (to be precise, xvalue), but still OK
您需要在您的示例中将 a
转换为右值以获得预期效果,因为变量名称本身是左值(这是 C++ 中左值和右值的棘手细节)。所以正如所写的那样,它是正确的 C++,但没有按照您的想法去做。
如果你施放它,使用std::move(a)
instead of just a
, the code now does what you want and is still correct. This is because of a special rule in C++ that temporaries can be bound to const lvalues, a more detailed discussion of which can be found here。当您使用如下代码时,此功能会非常方便:
void ProcessData(const std::vector<int>& input_vector);
然后您想使用以下内容对其进行测试:
ProcessData(std::vector<int>{1, 2, 3, 4, 5});
这使您不必在将对象作为 const 左值引用传递之前显式创建对象。注意这里的 const 很关键,没有它代码是不正确的。对此选择的理由有更详细的讨论 here。
考虑以下示例 struct
:
struct A {
int i;
void init(const A &a)
{
this->i = a.i;
}
A(int i)
{
this->i = i;
}
A(const A &a) = delete;
A &operator=(const A &a) = delete;
A(A &&a)
{
init(a); // Is this allowed?
}
A &operator=(A &&a)
{
init(a); // Is this allowed?
return *this;
}
};
右值引用 A &&a
被传递给接受 const A &a
的函数,即常量左值引用。这是否允许并导致 C++ 中明确定义的行为?
是的,允许。
注意,表达式 a
的值类别是左值,即使 a
声明的类型是右值引用。
此外,如果您使用 std::move
从 a
创建右值,您的代码仍然是格式正确的,因为右值可以绑定到 const 左值引用:
init(std::move(a)); // std::move(a) is an rvalue (to be precise, xvalue), but still OK
您需要在您的示例中将 a
转换为右值以获得预期效果,因为变量名称本身是左值(这是 C++ 中左值和右值的棘手细节)。所以正如所写的那样,它是正确的 C++,但没有按照您的想法去做。
如果你施放它,使用std::move(a)
instead of just a
, the code now does what you want and is still correct. This is because of a special rule in C++ that temporaries can be bound to const lvalues, a more detailed discussion of which can be found here。当您使用如下代码时,此功能会非常方便:
void ProcessData(const std::vector<int>& input_vector);
然后您想使用以下内容对其进行测试:
ProcessData(std::vector<int>{1, 2, 3, 4, 5});
这使您不必在将对象作为 const 左值引用传递之前显式创建对象。注意这里的 const 很关键,没有它代码是不正确的。对此选择的理由有更详细的讨论 here。