【问题标题】:When to use rvalue references with static storage duration?何时使用具有静态存储持续时间的右值引用?
【发布时间】:2016-07-05 07:10:15
【问题描述】:

C++11 允许在 global(,namespace, class) 范围内声明右值引用并具有静态存储持续时间。使用这些变量的好场景是什么?我进行了几次测试并提出了一些观察结果。以下代码将不编译 (g++ 5.3)

double&& m = 3.5;
double&& s() {return m;}

testy.cpp:在函数'double&& s()'中:

testy.cpp:7:22: 错误:无法将‘double’左值绑定到‘double&&’ double&& s() {return l;}

这是相当违反直觉的,即使我们声明了一个右值引用,它也被视为数据是按值返回的。当然,这是一个人为的例子,并且确实返回右值引用很少见。 但是为什么它不起作用?我的解释是,通过使用静态存储持续时间声明右值引用 m,我们得到了一种“通用引用”形式,这是 Scott 创造的术语迈耶斯(更多信息here)。通用引用的属性之一是它可以绑定到左值和右值。然而,与依赖于类型替换导致的引用崩溃的“通用引用”不同,我不清楚上述解决方案中涉及的机制。实际上下面的代码编译没有问题。

double&& m = 3.5;

int main() {
    double a {4.2};
    double& b = a;
    m = a;
    m = b;
    m = 3.2;
}

因此,如上所述,m 绑定到 double 的每一种风格。然而,变量具有静态存储持续时间的事实似乎与右值的性质相矛盾,右值绑定到临时对象。出现的问题很少。 为什么允许这样做?什么场景会使用这个属性?。我的第一个猜测是,我们可以使用它来提供接受任何“风格”参数的模板特化,这与通用引用的方式非常相似,只是它们与底层类型的绑定更加紧密。此外,“静态右值引用”的范围似乎并不重要,即具有静态存储持续时间和“函数”范围的右值也表现出如下所示的行为。

int main() {
    static double&& a = 4.2;
    double b = 3.2;
    double& c = b;
    a = b;
    a = c;
}

【问题讨论】:

  • id 表达式总是左值。 “右值引用”中的“右值”是指引用可以绑定到的值的种类。
  • 可能违反直觉,但rvalue reference 是lvalue :)
  • 我不明白你上次的演示。你不能写double& c = 1.2;
  • “事实上,下面的代码编译没有问题。[...] 因此,如上所述,m 绑定到每一种 double 类型。”你的例子绝对没有表明这一点。 a = b; 和 a = c; 是对绑定到 a 的对象的赋值。他们不会重新绑定引用。

标签: c++ c++11


【解决方案1】:

无法编译的原因在错误信息中:

testy.cpp:7:22: error: cannot bind ‘double’ lvalue to ‘double&&’ double&& s() {return l;}

命名变量总是左值 - l 是左值。 s() 返回一个右值。您必须使用演员表才能完成这项工作:

double&& s() {return std::move(m); }

为什么允许这样做?什么场景会用到这个属性?

真的值得为明确禁止它的语言添加一个例外吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-28
    • 2012-11-17
    • 2018-08-02
    • 2019-08-09
    • 1970-01-01
    相关资源
    最近更新 更多