【问题标题】:Direct-initializing an object inside a condition直接初始化条件内的对象
【发布时间】:2015-07-02 13:01:35
【问题描述】:

可以在if 语句的条件内定义和复制初始化变量:

if(int i = 17) { ... }

这也适用于用户定义的类型,因为它们重载了operator bool

if(Foo f = 42)      { ... }
if(Foo f = Foo(43)) { ... }

为什么我不能使用直接初始化,如下所示?

if(Foo f(51)) { ... }

GCC 发出 error: expected primary-expression before 'f'

Live on Coliru

除了“因为语法这么说”之外还有其他原因吗?我该如何解决它?

我正在使用 VC++03,其中Foo

  • 是一个对 RAII 敏感的对象,我注意没有为此定义一个复制构造函数
  • 是一个接受用户参数的模板
  • 有一个双参数构造函数

...所以我宁愿避免复制它或重复它的类型。

注意:虽然我的实际问题是 C++03,但我(学术上)对 C++11 中的答案很感兴趣。

【问题讨论】:

  • 您为什么认为声明Foo f = 42 意味着复制/移动?不应该复制省略工作吗?
  • @Columbo AFAIK 复制省略是一种优化,可能会执行或可能不会执行,但即使它不是对象也需要复制构造函数,我已禁用它以避免auto_ptr-like 邪恶。最后我通过 std::pair 解决了这个问题。
  • 传递std::pair 是如何解决这个问题的?如果它是从不同类型的复制初始化,您仍然需要一个复制构造函数。
  • @bogdan 确实如此。现在我想知道为什么它会起作用。

标签: c++ if-statement initialization c++03


【解决方案1】:

在 C++03 中,可以单独使用复制初始化语法:

选择语句
     if ( 条件 ) 语句
      […]

条件
     表达式
     type-specifier-seq declarator = 赋值表达式

从 C++11 开始,添加了列表初始化:

条件
表达式
attribute-specifier-seqoptdecl-specifier-seq declarator = initializer-clause
attribute-specifier-seqoptdecl-specifier-seq 声明符 支撑初始化列表

直接初始化的语法,即Foo f(…),大概被避免了,原因与它被禁止用于非静态数据成员初始化器的原因相同:歧义,尤其是“最令人烦恼的解析”。

【讨论】:

    【解决方案2】:

    因为 C++03 标准只允许在条件内进行赋值初始化:

    condition:
        expression
        type-specifier-seq declarator = assignment-expression
    

    【讨论】:

      【解决方案3】:

      鉴于您的限制,我相信在 C++03 中,您唯一的选择是在 if 语句之外声明变量,并为范围添加大括号:

      {
          Foo f(51, 52);
          if (f) {
              //...
          }
      }
      

      在 C++11 中,您可以利用大括号初始化语法:

      if (Foo f{51, 52}) {
          //...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-01
        • 2020-02-08
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 2018-02-03
        相关资源
        最近更新 更多