C++ 直接初始化条件内的对象

C++ 直接初始化条件内的对象,c++,if-statement,initialization,c++03,C++,If Statement,Initialization,C++03,可以在if语句的条件内定义和复制并初始化变量: if(int i = 17) { ... } 这也适用于用户定义的类型,因为它们重载了运算符bool: if(Foo f = 42) { ... } if(Foo f = Foo(43)) { ... } 为什么我不能像下面那样使用直接初始化 if(Foo f(51)) { ... } GCC发出错误:“f”之前应为主表达式 除了“因为语法上这么说”之外,还有其他原因吗?我怎样才能解决这个问题呢 我正在使用VC++03,其中Foo

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

if(int i = 17) { ... }
这也适用于用户定义的类型,因为它们重载了
运算符bool

if(Foo f = 42)      { ... }
if(Foo f = Foo(43)) { ... }
为什么我不能像下面那样使用直接初始化

if(Foo f(51)) { ... }
GCC发出
错误:“f”之前应为主表达式

除了“因为语法上这么说”之外,还有其他原因吗?我怎样才能解决这个问题呢

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

  • 是一个RAII敏感对象,我注意到没有为其定义复制构造函数
  • 是从用户获取参数的模板
  • 有一个双参数构造函数
。。。所以我宁愿避免复制它或重复它的类型


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

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

if (Foo f{51, 52}) {
    //...
}
选择语句:
如果(
条件
语句
[…]

条件:
表达式
类型说明符seq声明符
=
赋值表达式

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

条件:
表达式
属性说明符seqopt decl说明符seq声明符
=
初始值设定项子句

属性说明符seqopt decl说明符seq声明符 大括号初始列表


直接初始化的语法,即
Foo f(…)
,可能是因为与非静态数据成员初始值设定项不允许使用相同的原因而避免的:歧义,尤其是“最麻烦的解析”

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

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

考虑到您的限制,我相信在C++03中,您唯一的选择是在
if
语句之外声明变量,并为作用域添加大括号:

{
    Foo f(51, 52);
    if (f) {
        //...
    }
}
在C++11中,可以利用大括号初始化语法:

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

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