其他分享
首页 > 其他分享> > C构造函数调用顺序

C构造函数调用顺序

作者:互联网

当我初始化我的类的对象时,默认和复制构造函数都被调用.

class A
{
public:
   A (string s) { str = string (s); cout << "default" << endl; }
   A (int n) { cout << "A (int n)" << endl; }
   A (string s, int n) { cout << "A (string s, int n)" << endl; }
   A (int n2, string s2) { cout << "A (int n2, string s2)" << endl; }
   A (const A& a) { str = a.str; cout << "copy" << endl; }

   inline void printA () { cout << str << endl; }

   string str;
};


int main (void)
{
   A a_1 = A ("con 1");
   cout << endl;

   A a_2 = "con 2";
   cout << endl;

   A a_3 = A (4);

   A a_4 = A ("a_4", 10);
   cout << endl;

   A a_5 = A (11, "a_5");
   cout << endl;

   cin.get();
   return 0;
}

结果:

default
copy

default

A (int n)

A (string s, int n)
copy

A (int n2, string s2)
copy

为什么a_1,a_3和a_4同时调用默认构造函数和复制构造函数?
A_3也有一个参数,但它不需要复制构造函数.

解决方法:

A a_1 = A (“con 1”);

通过调用以字符串作为参数的构造函数构造临时对象,因为传递的类型是const char *,编译器必须首先执行隐式转换为string(),然后使用此临时对象复制构造新的a_1对象.
由于存在额外的隐式转换,因此编译器无法对此进行优化,并且需要调用复制构造函数.
根据评论和进一步的研究,我怀疑(上面的斜体)推理是否正确.

@David在他的评论中建议:
不能因为隐式转换而忽略副本,而是因为转换是显式的.也就是说,编译器无法对其进行优化,因为代码明确请求创建临时和复制结构.

但是,@ David和Me都无法通过标准引文来证实它.

A a_2 = “con 2”;

通过调用以字符串作为参数的相应构造函数来构造对象a_2.

A a_3 = A (4);

案例1中的注释也适用于此:
理想情况下应该通过调用构造函数构造一个临时对象,该构造函数将整数作为参数,然后使用此临时对象来复制构造一个新的a_3对象,如案例1所示,但编译器可以通过调用构造函数来优化并直接构造对象,该构造函数采用整数一个可用.

A a_4 = A (“a_4”, 10);

通过调用构造函数构造临时对象,该构造函数将字符串和整数作为参数,然后使用此临时对象复制构造新的a_4对象.

A a_5 = A (11, “a_5”);

通过调用构造函数构造临时对象,该构造函数将整数和字符串作为参数,然后使用此临时对象复制构造新的a_5对象.

请注意,您没有为您的类定义默认构造函数.

您可以通过避免在上述情况下通过不使用赋值(=)来创建临时构建对象来以更有效的方式实现相同的目的.

A a_1("con 1");
A a_2("con 2");
A a_3(4);
A a_4("a_4", 10);
A a_5(11, "a_5");

我的初步答案是尝试解释行为,但是当我在Ideone上的gcc-4.3.4上编译它时,我发现gcc足够智能以优化复制构造函数调用.没有一个案例调用复制构造函数.

我得出的结论是,每个编译器根据其智能可以或不能优化复制构造函数调用,例如,虽然标准不要求编译器执行此类优化,但每个编译器根据其能力评估这些表达式.

如果我错了,请免费为我添加推理评论.

标签:c,constructor,copy-constructor
来源: https://codeday.me/bug/20190902/1793759.html