C++ 为什么初始化对象的两种不同方式会给出不同的输出
考虑以下代码C++ 为什么初始化对象的两种不同方式会给出不同的输出,c++,constructor,static-members,C++,Constructor,Static Members,考虑以下代码 #include <iostream> using namespace std; class A { int x; public: A() { cout << "A's constructor called " << endl; } }; class B { public: static A a;
#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;
}
现在让我们考虑另一个类似的代码
#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的构造函数只被调用一次,而在第二种代码中,它被调用了两次
另外,两个输出&a和&B::a是不同的,这意味着它们是两个不同的对象
请解释为什么会这样。嗯,
B::a
是B的(公共)静态成员实例,它是一个非常常见的类a
。因此,记录的第一个A
的构造函数是B::A
,它应该在控件进入main
之前初始化,但是接下来您要创建一个A
本地到main
的单独实例,它是按照顺序与其他main
的本地变量一起构造的(这里,在所有的B
s之后,B::a
嗯,B::a
是B的(公共的)一个非常常见的类A
的静态成员实例。因此,记录的第一个A
的构造函数是B::A
的构造函数,它应该在控件进入main
之前初始化,但是接下来您要在main
本地创建一个单独的A
实例,它是按照与h其他main
的局部变量(在这里,在所有B
s之后),它自然地与第一个代码中的B::a
不同
调用了A
的复制构造函数,该构造函数不会生成任何输出。您可以自己定义它,然后在第一个代码中获得与第二个代码类似的输出。
调用A
的复制构造函数,它不会生成任何输出。您自己定义它,您将得到与第二个代码类似的输出
现在我的问题是,为什么在第一种情况下,A的构造函数只被调用一次,而在第二种代码中,它被调用了两次
因为在第一种情况下,您默认只初始化了静态B::a
,而复制初始化了本地a
在第二个对话框中,您默认初始化了这两个对象
关键的区别在于,您只在默认构造函数中打印消息,而不在复制构造函数中打印任何内容
另外,两个输出&a和&B::a是不同的,这意味着它们是两个不同的对象
没错。a
是一个局部变量,而B::a
是一个静态成员变量。它们是不同的对象
现在我的问题是,为什么在第一种情况下,A的构造函数只被调用一次,而在第二种代码中,它被调用了两次
因为在第一种情况下,您默认只初始化了静态B::a
,而复制初始化了本地a
在第二个对话框中,您默认初始化了这两个对象
关键的区别在于,您只在默认构造函数中打印消息,而不在复制构造函数中打印任何内容
另外,两个输出&a和&B::a是不同的,这意味着它们是两个不同的对象
这是正确的。
a
是一个局部变量,而B::a
是一个静态成员变量。它们是不同的对象。很容易理解,每当创建关联构造函数的类实例(对象)被调用时
现在我的问题是,为什么在第一种情况下,A的构造函数只被调用一次,而在第二种代码中,它被调用了两次
您直接在堆栈中创建第二个对象,在后面的例子中调用构造函数,第一个是静态的,第二个是通过下面的语句在堆栈中创建对象
A a ;
在第一种情况下,将调用copy构造函数,而不是构造函数,这就是为什么您不能第二次得到print语句的原因
A a = b1.getA();
很容易理解,无论何时创建类实例(对象),都会调用关联的构造函数 现在我的问题是,为什么在第一种情况下,A的构造函数只被调用一次,而在第二种代码中,它被调用了两次 您直接在堆栈中创建第二个对象,在后面的例子中调用构造函数,第一个是静态的,第二个是通过下面的语句在堆栈中创建对象
A a ;
在第一种情况下,将调用copy构造函数,而不是构造函数,这就是为什么您不能第二次得到print语句的原因
A a = b1.getA();
类类型的静态成员变量表示具有进程范围生命周期的存储。它在到达程序入口点(main()的开头)之前的某个点进行初始化。这是第一个构造函数调用 线路
A a = b1.getA();
通过调用复制构造函数初始化对象a,并且通过返回值优化和复制省略,没有默认的构造函数调用
第二种变体:
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 constructor called
A's copy constructor called
A's copy operator= called
类类型的静态成员变量表示具有进程范围生命周期的存储。它在到达程序入口点(main()的开头)之前的某个点进行初始化。这是第一个构造函数调用 线路
A a = b1.getA();
通过调用复制构造函数初始化对象a,并且通过返回值优化和复制省略,没有默认的构造函数调用
第二种变体:
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 constructor called
A's copy constructor called
A's copy operator= called
在这两种情况下都有两个独立的对象。这会给以前的答案增加什么?在这两种情况下都有两个独立的对象。这会给以前的答案增加什么?