>请考虑以下代码
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a = b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
输出为
A's constructor called
B's constructor called
B's constructor called
B's constructor called
0x7fff03081280
0x601194
现在让我们考虑另一个类似的代码
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a ;
a= b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
输出为
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
0x7ffc485a1070
0x601194
现在我的问题是,为什么在第一种情况下,A 的构造函数只被调用一次,而在第二种代码中它被调用两次。
此外,两个输出 &a 和 &B::a 是不同的,因此这意味着它们是两个不同的对象。
请解释为什么会这样。
在你的第一个代码中
A a = b1.getA();
调用A
的复制构造函数时,它不会生成任何输出。自己定义它,您将获得与第二个代码类似的输出。
嗯,B::a
是B的(公共(静态成员实例,否则是一个很常见的类A
。所以,记录的第一个A
构造函数是B::a
的构造函数,它应该在控件进入main
之前初始化,但接下来你创建一个单独的A
本地实例main
,它是与其他main
的局部变量一起构造的(这里,在所有B
之后(,它自然不同于B::a
。
现在我的问题是,为什么在第一种情况下,A 的构造函数只被调用一次,而在第二种代码中它被调用两次。
因为在第一种情况下,你默认只初始化静态B::a
,并复制初始化本地a
。
在第二个中,您默认初始化了这两个对象。
关键的区别在于,您只在默认构造函数中打印消息,而不在复制构造函数中打印任何内容。
此外,两个输出 &a 和 &B::a 是不同的,因此这意味着它们是两个不同的对象。
这是正确的。a
是局部变量,而B::a
是静态成员变量。它们是不同的对象。
类类型的静态成员变量表示具有进程范围生命周期的存储。它在到达程序入口点(main(( 的开头(之前的某个时间点被初始化。这是第一个构造函数调用。
该行
A a = b1.getA();
通过调用复制构造函数初始化对象 A,通过返回值优化和复制 elision 没有默认构造函数调用。
第二个变体:
A a; // A() call
a = b1.getA(); // operator= call
修改后的类
class A
{
int x;
public:
A(const A& a): x(a.x) { cout << "A's copy constructor called " << endl; }
A(A&& a): x(a.x) { a.x = 0; cout << "A's move constructor called " << endl; }
const A& operator=(const A& a) { x = a.x; cout << "A's copy operator= called " << endl; }
A() { cout << "A's constructor called " << endl; }
};
在第一种情况下会给出此输出:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's copy constructor called
第二种情况将导致:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
A's copy constructor called
A's copy operator= called
很容易理解,每当创建关联的构造函数时,都会调用类实例(对象(。
现在我的问题是,为什么在第一种情况下,A 的构造函数只被调用一次,而在第二种代码中它被调用两次。
您直接在堆栈中创建第二个对象,并且在稍后的情况下调用构造函数,第一个是静态的,第二个是通过以下语句在堆栈中创建对象。
A a ;
在第一种情况下,不是构造函数,而是调用复制构造函数,这就是为什么您第二次不会获得 print 语句的原因。
A a = b1.getA();