【问题标题】:Initializing reference variables with the conditional if else operator使用条件 if else 运算符初始化引用变量
【发布时间】:2012-03-01 06:54:12
【问题描述】:

以下 C++ 无效,因为引用变量需要初始化器:

int& a; // illegal
if (isfive) {
  a = 5;
} else {
  a = 4;
}

但是,MSVC 似乎认为这没问题:

int& a = isfive ? 5 : 4;

这对我来说意味着 MSVC 实际上将条件运算符视为单个表达式,而不是将其扩展为 if-else 语句。

使用条件运算符初始化引用是否总是有效的 C++?

【问题讨论】:

  • 我很好奇如果您尝试在装配级别上进行比较会发生什么...
  • 如何比较可编译的汇编代码和不编译的代码?
  • @MichaelKrelin:不幸的是,在 Visual C++ 中,这种非法代码是被接受的。 (第二种形式)。
  • @MichaelKrelin:所以我们真正拥有的是无法编译的代码和更多无法编译的代码,我同意很难比较程序集:)
  • @krynr,你是说第二个?参考暂时的,我想。我想知道有多短命......我实际上并不认为 OP 意味着两个常量,无论如何,他可能在谈论条件并想出了不幸的例子。

标签: c++ reference conditional-operator


【解决方案1】:

它是运算符,是表达式的一部分,而不是语句。而且你不能让参考未初始化,即使是很短的时间;-)

【讨论】:

    【解决方案2】:

    MSVC 有一个非标准的“扩展”。这意味着它允许损坏的代码。禁止这样做是有充分理由的。

    还要注意

    int& a = 5;
    

    在标准 C++ 中也不合法。

    不过,一般来说,使用任何可以转换为正确类型的表达式(包括使用条件运算符)初始化 const 引用是合法的。使用正确类型的左值初始化非const 引用是合法的,条件运算符在某些条件下会产生该左值。

    【讨论】:

    • 嗯,你知道什么,问这个问题解决了一个我什至不知道自己有的问题。谢谢!
    【解决方案3】:

    条件运算符是表达式,而不是语句。像这样初始化一个引用是完全可以的。这有点像通过调用函数来初始化引用。

    请注意,如果您将其绑定到临时文件,则您的引用必须是 const(MSVC++ 愚蠢地忽略了这一规则)。

    【讨论】:

    • 只有当我们忽略不能将非常量引用绑定到右值的事实时,才可以初始化这样的引用...(即@987654322 @ 可以,但int& r = isfive? 4 : 5; 不行)
    • @DavidRodríguez-dribeas 是的,我不久前添加了一条注释。
    【解决方案4】:

    您发布的代码无法使用 VC++ 2010 编译:

    错误 1 ​​错误 C2440: 'initializing' : 无法从 'int' 转换为 'int &'

    将行改为:

    const int& a = isfive ? 5 : 4; 
    

    让它编译。

    【讨论】:

    • 我假设您使用的是/Za(禁用语言扩展)选项?
    • @BenVoigt:不。看来问题已解决:technet.microsoft.com/en-us/query/szywdw8k
    • 我想知道在 TechNet 而不是 MSDN 上做了什么。仍然存在一些相关的错误,但很高兴看到最典型的情况得到修复。
    【解决方案5】:

    这样不行

    int& a = isfive ? 5 : 4;
    

    除非您将引用“a”声明为const

    【讨论】:

      【解决方案6】:

      三元运算符不会扩展为if-else 构造(不是根据语言,实现可能会生成等效的二进制文件,但在语言级别它们是不同的)。所以下面的代码是有效的:

      int four = 4, five = 5;
      int& r = condition? four : five;
      

      问题中的原始示例依赖于(错误地)允许将非常量引用绑定到右值表达式的 Microsoft 扩展。

      【讨论】:

        【解决方案7】:

        指针+参考技术

        确实感觉像是 C++ 语言的一个限制,可以通过新的语言特性来克服。

        在那之前我能看到的最有效的选择是使用指针,然后使用指针,然后设置对指针的引用以避免在以后每次使用变量时使用变量时进行多次取消引用:

        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++?

        相关:Declare a reference and initialize later?

        【讨论】:

          猜你喜欢
          • 2012-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-09
          • 2019-10-20
          • 2023-03-03
          • 1970-01-01
          • 2021-06-03
          相关资源
          最近更新 更多