定义两个变量:是“键入a(arg),b(arg);”完全等同于“Type a(arg); Type b(arg);”?

时间:2011-12-07 01:43:46

标签: c++ exception

假设我想要定义类{Type}的两个变量。构造函数需要1个参数。 以下两种方式是否完全等效(编译为相同的目标代码)?

Type a(arg), b(arg);

Type a(arg);
Type b(arg);

在我阅读了一篇关于异常安全的页面后出现了这个问题--- http://www.gotw.ca/gotw/056.htm 有一条准则“在其自己的代码语句中执行每个资源分配(例如,新),它立即将新资源提供给管理器对象。” 它给出了一个例子: 以下代码段是安全的

auto_ptr<T> t1( new T );
auto_ptr<T> t2( new T );
f( t1, t2 );

但下面这行不安全

f( auto_ptr<T>( new T ), auto_ptr<T>( new T ) );

那么,怎么样

auto_ptr<T> t1( new T ), t2( new T );
f( t1, t2 );

我查阅了C ++语言标准的文档,但没有发现任何指定此问题。

要浑水,怎么样

shared_ptr<T> t1( new T );
shared_ptr<T> t2( t1 );

shared_ptr<T> t1( new T ), t2( t1 );

3 个答案:

答案 0 :(得分:7)

是的,它们是等价的。见C ++ 11,8 / 3:

  

声明中的每个init-declarator都会被单独分析,就像它一样   本身就是声明 97

脚注97相当冗长,它表示T D1, D2, ... Dn;“通常”等同于T D1; T D2; ... T Dn;,例外情况是后续声明中T的含义受其影响的情况一个你做的。给出了两个例子:

struct S {};
S S, T; // is not equivalent to:
S S; S T;

auto i = 1, j = 2.0; // is not equivalent to:
auto i = 1; auto j = 2.0;

但在这两种情况下,其中一种替代方法是错误,因此这不会导致您不得不启动调试器。

无论如何,auto_ptr<T> t1( new T ), t2( new T );auto_ptr<T> t1( new T ); auto_ptr<T> t2( new T );

一样安全

请注意,无法保证等效源代码编译为相同的对象代码,只是它具有相同的含义。在您的示例中,包含调试注释的目标代码在源行数方面会有相当不同,但编译器可能会因某些不明原因或完全没有理由而引入意外差异。

答案 1 :(得分:2)

在为函数调用生成参数的同时构造new T之前,编译器可以自由地评估auto_ptr。如果在该序列的中间某处抛出异常,则可能会导致内存泄漏。

至于变量声明中发生的事情,请查看上一个问题:Is the comma in a variable list a sequence point?

答案 2 :(得分:2)

是的,根据定义:http://www.open-std.org/jtc1/sc22/wg21/docs/wp/html/oct97/decl.html

Each init-declarator in a declaration is analyzed separately as if it was in a
declaration by itself.