以下C ++无效,因为引用变量需要初始值设定项:
int& a; // illegal
if (isfive) {
a = 5;
} else {
a = 4;
}
然而,MSVC似乎认为这没关系:
int& a = isfive ? 5 : 4;
这对我来说意味着MSVC实际上将条件运算符视为单个表达式,而不是将其扩展为if-else语句。
使用条件运算符初始化引用是否总是有效的C ++?
答案 0 :(得分:7)
三元运算符不会扩展为if-else
构造(不是根据语言,实现可能会生成等效的二进制文件,但在语言级别它们是不同的)。因此以下代码有效:
int four = 4, five = 5;
int& r = condition? four : five;
问题中的原始示例取决于Microsoft扩展(错误地)允许将非const引用绑定到rvalue表达式。
答案 1 :(得分:5)
MSVC有一个非标准的“扩展名”。这意味着它允许破坏代码。这是被禁止的一个很好的理由。
另请注意
int& a = 5;
在标准C ++中也不合法。
但是,一般情况下,使用任何可以转换为正确类型的表达式初始化const
引用是合法的(包括使用条件运算符)。使用正确类型的左值初始化非const
引用是合法的,条件运算符在某些条件下会产生该值。
答案 2 :(得分:3)
条件运算符是表达式,而不是语句。初始化这样的引用是完全正确的。这有点像通过调用函数来初始化引用。
请注意,如果将其绑定到临时对象(MSVC ++愚蠢地忽略的规则),则您的引用需要为const
。
答案 3 :(得分:2)
您发布的代码无法使用VC ++ 2010进行编译:
错误1错误C2440:'初始化':无法从'int'转换为'int&'
将行更改为:
const int& a = isfive ? 5 : 4;
让它编译。</ p>
答案 4 :(得分:1)
不行
int& a = isfive ? 5 : 4;
除非您将引用“a”声明为const
。
答案 5 :(得分:0)
它是运算符,表达式的一部分,而不是语句。并且你不能在短时间内保留未初始化的参考; - )
答案 6 :(得分:0)
指针+参考技术
感觉确实是C ++语言的局限性,可以通过新的语言功能来克服。
在那之前,我能看到的最有效的选项(如果要在if中做更多的事情,而不仅仅是设置引用,在这种情况下,您可以使用三元运算符?
)是使用指针,然后将指针的引用设置为避免在以后每次使用变量时使用该变量时进行多次取消引用:
main.cpp
#include <iostream>
int main(int argc, char **argv) {
(void)argv;
int x = 1;
int y = 2;
int *ptr;
if (argc > 1) {
ptr = &x;
} else {
ptr = &y;
}
// One pointer dereference here, I don't see how to get rid of this.
int &z = *ptr;
// No pointer dereference on any of the below usages.
z = 3;
std::cout << x << std::endl;
std::cout << y << std::endl;
std::cout << z << std::endl;
}
编译:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
运行:
./main.out
输出:
1
3
3
再次运行:
./main.out a
输出:
3
2
3
但是,如果在编译时知道if条件,则当然可以使用预处理器或更好的预处理器,C ++ 17 if constexpr
:if / else at compile time in C++?
答案 7 :(得分:0)
我已经删除了有条件的
int& a = 5;
if (!isfive) a = 4;