这个问题可能没有最好的标题,但这里的代码将解释我想问的问题。
此代码运行并打印“左值”,但如果我从 MyPair 的第一种类型中删除
const
,它会给出预期的输出,即“右值”。我想知道const
在这里扮演什么角色?
#include <iostream>
#include <utility>
#include <string>
using MyPair = std::pair<const std::string, int>;
void func(std::string&& str)
{
std::cout << "rvalue" << std::endl;
}
void func(const std::string& str)
{
std::cout << "lvalue" << std::endl;
}
template<typename T>
void func_forward(T&& p)
{
func(std::forward<T>(p).first);
}
void test(MyPair&& p)
{
func_forward(std::move(p));
}
int main()
{
test({"hello", 3});
return 0;
}
在 C++ 中,右值是一个临时对象,在内存中没有稳定的位置。我们可以获取左值的地址,但不能获取右值的地址。右值可以绑定到右值引用 (
T&&
) 以延长其生命周期,也可以绑定到对 const
(const T&
) 的左值引用,但不能绑定到普通左值引用 (T&
)。
当该对的第一个元素声明为
const
时,您无法将非常量右值引用 (std::string&&
) 绑定到它。原因是它可以允许修改 const 对象,而这在 C++ 中是不允许的。因此,选择左值的重载,即 void func(const std::string& str)
。
这里重要的一点是
std::string&&
和 const std::string&
不是一回事。第一个是对临时字符串(可以修改)的引用,第二个是 const 左值引用,可以引用左值或右值,但不允许修改它所引用的对象。
当您从
const
中删除 MyPair
时,第一个参数变得可修改,因此,允许将其绑定到非常量右值引用 (std::string&&
)。因此,在这种情况下,将调用 func
函数的右值版本。
总结一下,这里
const
的作用就是限制对象的修改。如果一个对象是 const
,则无法将非常量右值引用绑定到它,因为它将允许修改 const 对象。