这个问题可能没有最好的标题,但这里的代码将解释我想问的问题。
这段代码运行并打印“lvalue”,但如果我从MyPair的第一个类型中删除const
,它会给我预期的输出,即“rvalue”。我想知道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;
}
字符串
3条答案
按热度按时间ac1kyiln1#
没有任何东西被转换为左值。
std::forward<T>(p).first
在你的例子中的示例化是一个右值(特别是xvalue),而不管const
是什么。但是,它的 type 将是const std::string
或std::string
,具体取决于MyPair
类型中const
的选择。问题是你用
func
区分左值和右值的方法是不正确的,因为func
的参数的第一个重载不是const
限定的,所以只接受非const
std::string
类型的右值。另一方面,第二个
func
重载可以接受任何值类别和const
-限定,因为const
左值引用可以绑定到左值和右值。因此,如果first
是const
合格的,则将选择它作为唯一可行的重载,而不管值类别如何。要修复检测方法,请在第一个
func
重载中使用const std::string&&
而不是std::string&&
作为参数类型。twh00eeo2#
基本上,将
const
添加到对的第一个成员意味着您将const std::string
类型的x值传递给func
,而右值引用std::string&&
不能绑定到该值,因为它将丢弃const
限定符。在两个重载中,第一个成员上有
const
:func(std::string&&)
无法调用func(const std::string&)
,因为const std::string&
也可以绑定到xvalues一旦从对的第一个成员中删除
const
:func(std::string&&)
更适合std::string
类型的x值,因为它不需要限定转换func(const std::string&)
需要一个限定转换(以添加const
),因此它在重载解析中失败请注意,
std::forward<T>(p).first
不会变成左值,无论first
是否是const
。假设p
是一个右值引用,这个表达式总是一个xvalue。pgvzfuti3#
在C中,右值是在内存中没有稳定位置的临时对象。我们可以接受左值的地址,但不能接受右值的地址。一个右值可以绑定到一个右值引用(
T&&
)来延长它的生存期,也可以绑定到const
(const T&
)的左值引用,但不能绑定到普通的左值引用(T&
)。当对的第一个元素被声明为
const
时,你不能将一个非常量右值引用(std::string&&
)绑定到它。原因是它可以允许修改const对象,这在C中是不允许的。因此,选择左值的重载,即void func(const std::string& str)
。这里的重点是
std::string&&
和const std::string&
不是一回事。第一个是对临时字符串的引用(可以修改),第二个是const左值引用,可以引用左值或右值,但不允许修改它引用的对象。当从
MyPair
中删除const
时,第一个参数变为可修改的,因此允许将其绑定到非常量右值引用(std::string&&
)。因此,在这种情况下,func
函数的右值版本被调用。综上所述,
const
在这里的作用是限制对象的修改。如果一个对象是const
,你不能绑定一个非const右值引用到它,因为它允许修改一个const对象。