关于C++中声明语法的技巧问题

rmn*_*rmn 9 c++ syntax

看看这里:在下面的代码中,b的类型是什么?

struct A {
    A (int i) {}
};

struct B {
    B (A a) {}
};

int main () {
    int i = 1;
    B b(A(i)); // what would be the type of b
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果有人能够彻底向我解释为什么会存在这样的语法,我将不胜感激:)

谢谢.

Kir*_*sky 7

它是根据C++标准8.2/1的本地函数声明.您可以使用隐式构造函数来避免这种情况或以下情况:

B b(A(i)); // is equal to B b( A i );

// ---

// to declare variable of type B write:
B b = A(i);
// explicit form if you want:
B b( static_cast<A>(A(i)) );
// or
B b( (A)i );
Run Code Online (Sandbox Code Playgroud)

C++标准8.2/1:

函数式转换与6.8中提到的声明之间的相似性所产生的模糊性也可以在声明的上下文中出现.在该上下文中,选择在函数声明与参数名称周围的冗余括号集和具有函数样式转换作为初始化器的对象声明之间.正如6.8中提到的含糊不清一样,决议是考虑任何可能是声明声明的结构.


Omn*_*ous 7

C的一个瑕疵(和C++继承它(并使其变得更糟))是没有特殊的语法来引入声明.这意味着声明通常看起来像可执行代码.另一个例子:

A * a;
Run Code Online (Sandbox Code Playgroud)

这是A乘以a,还是声明了什么?为了理解这一行,你必须知道A是一个类型的名称.

C++中的基本规则是,如果可以将某些东西解析为声明,那么它就是.在这种情况下,它会导致奇怪而令人惊讶的结果.函数声明看起来很像函数调用,特别是(在A之后可以想到几种方式).

您可以在此示例中使用额外的括号来解决此问题,这些括号会删除编译器将代码解析为声明的能力.

B b((A(i)));
Run Code Online (Sandbox Code Playgroud)

在C中,这不是模糊的,因为没有构造函数调用的函数样式,因为没有构造函数.A是类型的名称,或者是函数的名称.它不可能两者兼而有之.

  • 我相信你也可以这样做:B b = B(A(i)); (2认同)
  • ......但意思是另一回事 - "B b = B(...)`要求`B`有一个复制构造函数(即使编译器可以优化对它的调用,仍然需要检查),而`B b(...)`不需要它. (2认同)

Unc*_*ens 5

B b(A(i)); 
Run Code Online (Sandbox Code Playgroud)

相当于

B b(A i);
Run Code Online (Sandbox Code Playgroud)

- 参数名称周围的括号是可选的 - 相当于

B b(A);
Run Code Online (Sandbox Code Playgroud)

- 参数名称在函数声明中是可选的.因此它是一个函数声明.

通常你会遇到它

X x();
Run Code Online (Sandbox Code Playgroud)

- 不是预期的默认构造函数 - 但是在使用临时工具时有更复杂的情况,例如

vector<int> v(istream_iterator<int>(cin), istream_iterator<int>());
Run Code Online (Sandbox Code Playgroud)