c++ 为什么将右值绑定到常量类型会使其成为左值?

up9lanfz  于 2023-08-09  发布在  其他
关注(0)|答案(3)|浏览(109)

这个问题可能没有最好的标题,但这里的代码将解释我想问的问题。
这段代码运行并打印“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;
}

字符串

ac1kyiln

ac1kyiln1#

没有任何东西被转换为左值。
std::forward<T>(p).first在你的例子中的示例化是一个右值(特别是xvalue),而不管const是什么。但是,它的 type 将是const std::stringstd::string,具体取决于MyPair类型中const的选择。
问题是你用func区分左值和右值的方法是不正确的,因为func的参数的第一个重载不是const限定的,所以只接受非conststd::string类型的右值。
另一方面,第二个func重载可以接受任何值类别和const-限定,因为const左值引用可以绑定到左值和右值。因此,如果firstconst合格的,则将选择它作为唯一可行的重载,而不管值类别如何。
要修复检测方法,请在第一个func重载中使用const std::string&&而不是std::string&&作为参数类型。

twh00eeo

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。

pgvzfuti

pgvzfuti3#

在C中,右值是在内存中没有稳定位置的临时对象。我们可以接受左值的地址,但不能接受右值的地址。一个右值可以绑定到一个右值引用(T&&)来延长它的生存期,也可以绑定到constconst 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对象。

相关问题