C++ 初始化列表与赋值

Posted

技术标签:

【中文标题】C++ 初始化列表与赋值【英文标题】:C++ initialization list vs assigning values 【发布时间】:2020-05-11 03:17:19 【问题描述】:

在 C++ 中,初始化列表和在构造函数中赋值而不是每个方法的外观有什么区别? 我的意思是使用一个而不是另一个的优点是什么,为什么在幻灯片(下)的给定示例中仅适用于初始化? (我没找到,希望能加点资源)

Click here to view slide: uploaded on imgur

【问题讨论】:

【参考方案1】:

在构造函数中使用初始化列表是一步过程,即它在声明对象的那一刻初始化对象。它调用复制构造函数。

而使用分配是两步过程,即定义对象然后分配它。定义对象调用默认构造函数,然后赋值调用赋值运算符。因此,昂贵的操作。

在C++中,类的常量或引用数据成员变量只能在初始化列表中初始化,不能在构造函数体中使用赋值。

常量和引用数据成员变量都具有必须在声明时初始化的属性。因此,只有在构造函数中使用初始化列表,因为初始化列表在声明时初始化类成员变量,而如果构造函数主体在声明后初始化数据成员,则赋值。

在某些情况下,构造函数内的数据成员初始化不起作用,必须使用初始化列表。以下是此类情况。

    用于初始化非静态 const 数据成员。
#include<iostream> 
using namespace std; 

class Test  
    const int t; 
public: 
    Test(int t):t(t)   //Initializer list must be used 
    int getT()  return t;  
; 

int main()  
    Test t1(10); 
    cout<<t1.getT(); 
    return 0; 

    用于引用成员的初始化。
#include<iostream> 
using namespace std; 

class Test  
    int &t; 
public: 
    Test(int &t):t(t)   //Initializer list must be used 
    int getT()  return t;  
; 

int main()  
    int x = 20; 
    Test t1(x); 
    cout<<t1.getT()<<endl; 
    x = 30; 
    cout<<t1.getT()<<endl; 
    return 0; 

    用于初始化没有默认构造函数的成员对象。 (在您的情况下 Array digits 没有默认构造函数)
#include <iostream>
using namespace std;
class A  
    int i; 
public: 
    A(int ); 
; 

A::A(int arg)  
    i = arg; 
    cout << "A's Constructor called: Value of i: " << i << endl; 
 

// Class B contains object of A 
class B  
    A a; 
public: 
    B(int ); 
; 

B::B(int x):a(x)   //Initializer list must be used 
    cout << "B's Constructor called"; 
 

int main()  
    B obj(10); 
    return 0; 

    用于基类成员的初始化。 当构造函数的参数名称与数据成员相同时。 出于性能原因。

【讨论】:

【参考方案2】:

如果不使用初始化列表,则在到达构造函数主体之前,将默认构造类的数据成员:


class Foo
    private:
        int bar;

    public:
        Foo(int _bar)//bar is default constructed here
            bar = _bar; //bar is assigned a new value here
        
;

这对于基本类型(如int)来说不是什么大问题,因为默认构造函数并不昂贵。但是,如果数据成员没有默认构造函数,或者默认构造后赋值比直接构造更昂贵,则可能会成为问题:

//Bar does not have a default constructor, only a copy constructor
class Bar
    public:
        Bar() = delete; //no default constructor
        Bar(const Bar& bar); //copy constructor only
;

class Foo
    private:
        Bar bar;

    public:
        Foo(const Bar& _bar)
            //this will not compile, bar does not have a default constructor
            //  or a copy assignment operator
            bar = _bar;
        

        Foo(const Bar& _bar) : bar(_bar)//this will compile, copy constructor for bar called
        
;

一般来说,使用初始化列表可以获得更高效的代码。

【讨论】:

嗨,为什么“Bar 没有默认构造函数”我在读到,当我们不编写构造函数时,编译器会为我们提供默认构造函数,除非我们声明其他任何构造函数......另外,可以举个例子详细说明一下:“但是,如果数据成员没有默认构造函数,或者默认构造后赋值比直接构造更昂贵,则可能会成为问题:” @clark_smith1 如果您查看第二个代码 sn-p,我已经使用 Bar()=delete 显式删除了 Bars 默认构造函数。这可以防止编译器构造一个。因此,Bar 没有任何构造函数。

以上是关于C++ 初始化列表与赋值的主要内容,如果未能解决你的问题,请参考以下文章

c++ 初始化列表VS构造函数内赋值初始化成员变量

c++ 初始化列表VS构造函数内赋值初始化成员变量

c++初始化函数列表

C++构造函数的初始化列表

依赖项没有复制 ctor 或赋值运算符时的 C++ 初始化程序列表

C++初始化列表