int类型的构造方法

时间:2011-03-18 09:29:45

标签: c++

考虑到成本,这些情况是否相同?

// case 1
int a = 5;

// case 2
int a (5);

// case 3
int a;
a = 5

5 个答案:

答案 0 :(得分:15)

第一个和第二个完全相同,都是初始化。第三个是不同的,因为这是赋值。这些差异符合C ++标准。但是,编译器可以将所有三个都视为相同!

答案 1 :(得分:14)

这三种语法是不同的,当我使用用户定义的类型而不是int时,请耐心等待,稍后我会回到int。

T a(5);     // Direct initialization
T b = 5;    // Implicit conversion (5->tmp) + copy-initialization
T c; c = 5; // Default initialization + assignment

在第一种情况下,对象a是通过构造函数构造的,该构造函数采用int或可以从int隐式转换的类型。

struct T {
  T( int ); // T a(5) will call this directly
};

在第二种情况下,类型T的临时对象是由int隐式转换创建的,然后该临时对象用于复制构造 b。允许编译器优化代码并仅执行隐式转换代替最终对象(而不是使用它来创建临时对象。但所有限制都必须经过验证

class T {
   T( T const & );
public:
   explicit implicit T( int );
};
int main() {
   T b = 5;   // Error 1: No implicit conversion from int to T.
              //     Fix: remove the `explicit` from the constructor
              // Error 2: Copy constructor is not accessible
}

第三种情况是默认构造,然后是作业。对类型的要求是它可以是默认构造的(有一个没有参数的构造函数,或者根本没有用户定义的构造函数,编译器将隐式定义它)。该类型必须可以从int分配,或者必须存在从int到可以分配给U的{​​{1}}类型的隐式转换。如您所见,树案例中的类型要求不同。

除了不同操作的语义之外,还有其他重要的区别,并非所有这些都可以在所有上下文中使用。特别是,在类的初始化列表中,您不能使用隐式转换+复制初始化版本,并且您只能使用默认构造+分配的前半部分。 / p>

T

在第一种情况下,使用值// OK // error // ok but different struct test { struct test { struct test { T x; T x; T x; test(int v) : x(v) {} test(int v) : x=5 {} test( int v ) { x = v; } 直接初始化属性x。第二种情况是语法错误。第三种情况是默认初始化,然后在构造函数的主体内部进行分配。

回到v示例,类型满足所有要求,因此编译器为这三种情况生成的代码几乎没有差异,但仍然无法使用{{初始化列表中的1}}版本用于初始化整数属性。此外,如果一个类的成员属性是一个常量整数,那么当它进入构造函数块时,你不能使用等价的int(上面的第三列),因为成员属性变为int b = 5;,是,int c; c =5;上面会试图修改一个常量,编译器会抱怨。

至于每个人的成本,如果可以使用它们,则const(对于任何POD类型)会产生相同的成本,但对于具有默认构造函数的用户定义类型则不然,在这种情况下,x = v;将产生默认构造的成本,然后是分配的成本。在另外两种情况下,标准明确声明允许编译器生成完全相同的代码(一旦检查了约束)。

答案 2 :(得分:4)

对于前两个,没有区别。

从标准文档 8.5.11

  

初始化的形式(使用括号或=)通常无关紧要,但在初始化程序或   正在初始化的实体具有类类型; 见下文。带括号的初始化程序只能在表达式时才是表达式列表   正在初始化的实体具有类类型。

第三个不是初始化,而是作业。

考虑到成本,

在前两种情况下,您将创建一个值为5的整数。

在第三种情况下,您将创建一个带有未定义值的整数,并将其替换为5 ..

答案 3 :(得分:3)

如果使用优化编译器,它们将全部编译为相同的代码。所以他们都有相同的成本。

答案 4 :(得分:1)

是的,它们都评估完全相同的汇编程序表示。你可以测试这个,例如通过编写虚函数然后生成汇编程序输出来使用GCC:g++ -S file.cxx -o file.s