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 

在这两种情况下都有两个独立的对象。这会给以前的答案增加什么?在这两种情况下都有两个独立的对象。这会给以前的答案增加什么?