为什么两种不同的对象初始化方式给出不同的输出



>请考虑以下代码

#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(); 

最新更新