19

构造函数和初始化列表之间的执行时间是否有任何差异?(或者这只是编码偏好的问题)。我有一组需要经常创建的对象,并且想知道使用初始化列表而不是构造函数是否有任何性能提升。

如果我要创建一百万个 A 类实例和另外一百万个 B 类实例,那么哪个选择会更好(对象代表网络中生成的数据包,因此这些数字)。

 class A {
   private:
     int a, b;

   public:
     A(int a_var, int b_var):a(a_var), b(b_var) {}; 
 };

 class B {
   private:
     int a, b;

   public:
     B(int a_var, int b_var) {
        a = a_var;
        b = b_var;
     }
};

如果任何构造函数对于原始类型来说比另一个更快(如示例中所示),如果将 a 和 b 替换为类型会更快吗?

类型示例:

 class AType {
   private:
     string a, b;

   public:
     AType(string a_var, string b_var):a(a_var), b(b_var) {}; 
};
4

5 回答 5

16

不同之处在于没有琐碎的默认构造函数的类型,编译器会在您的类中为您调用该构造函数B。您的课程B相当于:

 class B {
   private:
     SleepyInt a, b;

   public:
     // takes at least 20s
     B(int a_var, int b_var) : a(), b()
     //                      ^^^^^^^^^^ 
     {
        a = a_var;
        b = b_var;
     }
  };

如果您没有将成员变量或基类构造函数放在初始化列表中 - 它会为它们调用默认构造函数。int是基本类型 - 它的默认构造函数没有任何成本 - 所以在你的示例中没有区别,但对于更复杂的类型,构造函数+赋值可能不仅仅是构造成本。

一些有趣的例子,只是为了说明区别:

class SleepyInt {
public:
  SleepyInt () { 
    std::this_thread::sleep_for(std::chrono::milliseconds( 10000 ));  
  }
  SleepyInt (int i) {}
  SleepyInt & operator = (int i) { return *this; }
};

class A {
   private:
     SleepyInt a, b;

   public:
     A(int a_var, int b_var):a(a_var), b(b_var) {}; 
 };

 class B {
   private:
     SleepyInt a, b;

   public:
     // takes at least 20s
     B(int a_var, int b_var) {
        a = a_var;
        b = b_var;
     }
};
于 2012-11-03T22:53:15.740 回答
9

在构造函数中使用初始化列表而不是赋值是普遍接受的做法,这是有充分理由的。

初始化列表可用于初始化 POD(普通旧数据)和用户定义类型。初始化 POD 类型时,效果与赋值运算符完全相同,这意味着 POD 类型的构造函数中的初始化列表或赋值之间没有性能差异。

当我们考虑非 POD 类型时,事情会变得更有趣。在调用构造函数之前,先调用父类的构造函数,然后调用任何包含的成员,默认情况下调用无参数构造函数。使用初始化列表,您可以选择调用哪个构造函数。

所以要回答这个问题,存在性能差异,但仅在初始化非 POD 类型时。

于 2012-11-03T23:29:03.077 回答
4

如果成员的类型或多或少复杂,那么赋值初始化将首先导致默认的构造函数调用,然后调用operator=,这可能需要更长的时间。

于 2012-11-03T22:45:41.750 回答
2

如果类型是内置/固有类型,则不会有性能改进。

那说:

结论:在所有其他条件相同的情况下,如果您使用初始化列表而不是赋值,您的代码将运行得更快。

于 2012-11-03T22:48:03.770 回答
2

初始化列表是有用的引用类型、成员类对象或 const 成员。否则需要更多时间。

看我的测试代码:

#include <iostream>
#include <ctime>

using namespace std;

class A{
    int a;
public:
    A(int a_):a(a_){}
};

class B{
    int b;
public:
    B(){
    }

    B(int b_){
        b=b_;
    }
};

class C{
    B b;
public:
    C(int c_):b(c_){
    }
};

class D{
    B b;
public:
    D(int d_){
        b=d_;
    }
};

int main()
{
    clock_t start1[10], start2[10], end1[10], end2[10];
    for(int j=0;j<10;j++){
        start1[j]=clock();
        for(int i=0;i<100000;i++){   
            A *newA=new A(i);
            delete newA;
        }
        end1[j]=clock();
        start2[j]=clock();
        for(int i=0;i<100000;i++){   
            B *newB=new B(i);
            delete newB;
        }
        end2[j]=clock();
    }
    double avg1=0, avg2=0;
    for(int i=0;i<10;i++){
        avg1+=(end1[i]-start1[i]);
        avg2+=(end2[i]-start2[i]);
    }
    cout << avg1/avg2 << endl;

    for(int j=0;j<10;j++){
        start1[j]=clock();
        for(int i=0;i<100000;i++){   
            C *newC=new C(i);
            delete newC;
        }
        end1[j]=clock();
        start2[j]=clock();
        for(int i=0;i<100000;i++){   
            D *newD=new D(i);
            delete newD;
        }
        end2[j]=clock();
    }
    avg1=avg2=0;
    for(int i=0;i<10;i++){
        avg1+=(end1[i]-start1[i]);
        avg2+=(end2[i]-start2[i]);
    }
    cout << avg1/avg2 << endl;

    system("pause");
    return 0;
}



示例输出如下:

1.02391
0.934741

于 2013-09-02T13:36:54.657 回答