为啥右值不能分配给 constexpr 引用变量

Posted

技术标签:

【中文标题】为啥右值不能分配给 constexpr 引用变量【英文标题】:why rvalue can't assign to constexpr reference variable为什么右值不能分配给 constexpr 引用变量 【发布时间】:2016-05-03 12:00:31 【问题描述】:

我有以下代码

constexpr int into(int a,int b)

  int c=a*b;
  return c;


int main()

 constexpr int &n=into(5,5);


我已经阅读(在 MSDN 中)

关键字constexpr 是在 C++11 中引入并在 C++14 中改进的。这意味着不断的表达。与const 一样,它可以应用于变量,以便在任何代码尝试修改该值时引发编译器错误。

阅读后,我认为constexpr 可以代替const,但是对于上面的代码,我得到一个编译器错误说明

`int main()':
invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'`

constexpr 替换为const 时,它可以正常工作。我不明白这种行为;有人能解释一下吗?

【问题讨论】:

constexpr 引用必须绑定到全局变量。见答案here。 @flatmouse,感谢重播...链接中的答案之一是“引用在概念上等同于获取变量的地址,而局部变量的地址不是常量”在这里当我使用 const 它绑定。但不仅对于 constexpr。我相信 const 和 constexpr 对变量的行为是相同的 问题可能是into 的返回值没有保存在任何地方,但是您确实保存了对该返回值的引用,那么该引用必须指向哪里? 需要保存吗?函数调用是否暂时不将结果保存在任何地方,编译器 RVO 是否起作用? 【参考方案1】:

const 应用于int 不同,constexpr 关键字将 const 直接应用于引用类型为int& 的变量,这没有任何作用。

typedef int &int_ref;

int main() 
    int x = 1;
    int &a = x;          // OK
    int_ref b = x;       // OK, int_ref is 'int &'
    const int &c = 1;    // OK, reference to const int
    const int_ref d = 1; // error: type of d is 'int &'
                         // qualifier on reference are being ignored

constexpr int &nconstexpr int_ref n是一样的, 而const int &nconst int_ref n 的限定符不同。

【讨论】:

【参考方案2】:

标记为constexpr 的表达式将在编译时解析,这会将into(5,5) 的结果视为int 文字。众所周知,引用不能绑定到 C++ 中的 int 文字。

您可以通过使constexpr int x=into(5,5); 出现在全局范围内并在主范围内创建constexpr const int 引用来完成这项工作绑定x:

constexpr int into(int a,int b) 
  int c=a*b;
  return c;


// guaranteed to be resolved before main is called
constexpr int x = into(5,5);

int main() 
 constexpr const int& n = x;
 static_assert(n == 25, "whoops!");

为了具体回答您的问题,这与右值或移动语义完全正交,而是constexpr 的细微差别。

如果全局作用域让您心痛,您也可以将 x 设为 static 并将其初始化放在其引用绑定之前,这对我来说似乎更自然:

constexpr int into(int a,int b) 
  int c=a*b;
  return c;
  

int main() 
 // guaranteed to be resolved before main is called
 static constexpr int x = into(5,5);
 constexpr const int& n = x;
 static_assert(n == 25, "whoops!");

【讨论】:

"我们知道,引用不能绑定到 C++ 中的 int 字面量。",你的意思是什么引用? @erip,不清楚你说的 'into(5,5) 作为 int 文字。正如我们所知,引用不能绑定到 C++ 中的 int 文字。我相信调用 into() 函数返回 int&& 这是一个右值,它应该分配给常量引用,当我把 const int &n=into(5,5); main..if const can 为什么 constexpr 不能是 constexpr 缺少一些东西来处理这种情况 @PiotrSkotnicki 我的意思是对 int 文字的引用。 :) int& x = 25; 不合法。您当然可以将 const 引用到 int 文字,但这与我理解的 constexpr 的分辨率不同。 @erip 那么根据你的推理应该可以写成constexpr const int& @RichardGeorge 澄清:您认为constconstexpr 相同是错误的。 constexpr 表示“在编译时已知”,const 表示“在每次迭代分配后无法更改”。 const int i& = n; 将 i 分配给本轮的任何 n,但我们不能通过 i 进行修改。 constexpr i = 25 表示 i 在编译期间可以省略并替换为 25。

以上是关于为啥右值不能分配给 constexpr 引用变量的主要内容,如果未能解决你的问题,请参考以下文章

哪些值可以分配给 `constexpr` 引用?

C++11 左值右值右值引用详解

在 C++11 中对数组进行右值引用的目的是啥?

C++11 中的左值引用和右值引用的区别

为啥不能使用右值来初始化左值引用?

cpp►C++11右值引用移动语义移动构造函数移动赋值运算符