c++中的构造函数

C++中的构造函数可以分为一下几种:

  • 默认构造函数
  • 初始化构造函数(有参数)
  • 拷贝构造函数
  • 移动构造函数(move和右值引用)
  • 委托构造函数
  • 转换构造函数
#include <iostream>
using namespace std;

class Student{
public:
    Student(){//默认构造函数,没有参数
        this->age = 20;
        this->num = 1000;
    };  
    Student(int a, int n):age(a), num(n){}; //初始化构造函数,有参数和参数列表
    Student(const Student& s){//拷贝构造函数,这里与编译器生成的一致
        this->age = s.age;
        this->num = s.num;
    }; 
    Student(int r){   //转换构造函数,形参是其他类型变量,且只有一个形参
        this->age = r;
        this->num = 1002;
    };
    ~Student(){}
public:
    int age;
    int num;
};
int main(){
    Student s1;
    Student s2(18,1001);
    int a = 10;
    Student s3(a);
    Student s4(s3);
    
    printf("s1 age:%d, num:%d\n", s1.age, s1.num);
    printf("s2 age:%d, num:%d\n", s2.age, s2.num);
    printf("s3 age:%d, num:%d\n", s3.age, s3.num);
    printf("s2 age:%d, num:%d\n", s4.age, s4.num);
    return 0;
}
//运行结果
//s1 age:20, num:1000
//s2 age:18, num:1001
//s3 age:10, num:1002
//s2 age:10, num:1002
  • class Person
    {
    public:
        Person() :Person(1, 'a') {}                //委托构造函数
        Person(int i) : Person(i, 'a') {}           //委托构造函数
        Person(char ch) : Person(1, ch) {}     //委托构造函数
     
    private:
        Person(int i, char ch) :type(i), name(ch) {/*其他初始化信息*/}
        int type{ 1 };
        char name{ 'a' };
    };  
  • 默认构造函数和初始化构造函数在定义类的对象,完成对象的初始化工作
  • 复制构造函数用于复制本类的对象
  • 转换构造函数用于将其他类型的变量,隐式转换为本类对象

 

class A
{
public:
    int a;
    A(int i) :a(i)
    {
        std::cout << "a" << i << " 构造" << std::endl;
    }
    ~A()
    {
        std::cout << "a" << a << " 析构" << std::endl;
    }
    A(const A& another) {
        a = another.a;
        std::cout << "A 拷贝" << another.a << std::endl;
    }
   /*A(const A&& another) {
        a = another.a;
        std::cout << "A 移动" << another.a << std::endl;
    }*/
    A& operator=(const A& another) {
        a = another.a;
        std::cout << "A =" << another.a << std::endl;
        return *this;
    }
};

A func(int k) {
    std::cout << "func" << std::endl;
    A res(k);
    return res;
}

int main()
{
    std::cout << "a1" << std::endl;
    A a1 = A(1);
    std::cout << "a2" << std::endl;
    A a2(2);
    a2 = func(-2);
    std::cout << "a3" << std::endl;
    A a3 = func(-3);
    return 0;
}

 

//vs2022运行结构

 即用=初始化也属于拷贝构造函数。

此处需注意func函数被返回值优化,所以在函数内部仅存在一次构造和一次析构函数,若去掉优化则会变为一次构造,一次拷贝,两次析构,这是因为没有优化的时候,需要自己去创建一个临时对象,再将其拷贝到返回值上,而通过优化可以减少这些开销。

 

关于类成员初始化

一般对类成员初始化有两种方式,一种是使用初始化列表,一种是在构造函数内直接赋值。推荐使用初始化列表。

在函数内赋值初始化是在类成员已经申请完空间后执行的,也就是说当进入构造函数时,所有类成员均已被分配内存空间。因此此时再对类成员赋值相当于执行运算符=。

而使用初始化列表,是直接对类成员进行拷贝初始化,避免了初始化完之后再调用运算符=这一过程。

需注意以下情况必须使用初始化列表进行初始化:

① 当初始化一个引用成员时;

② 当初始化一个常量成员时;

③ 当调用一个基类的构造函数,而它拥有一组参数时;

④ 当调用一个成员类的构造函数,而它拥有一组参数时;

 

c++11支持对数据成员提供一个初始值,即在声明成员时可以直接使用=给其一个初始值。但是需注意不能使用圆括号()提供初始值,是因为使用()提供初始值则会使其和函数声明形式一致。

class A
{
public: 
  int x=1;  //合法
  B z(1);    //该形式无法区分其到底是成员函数还是成员变量
};

 

 

参考文章:https://interviewguide.cn/notes/03-hunting_job/02-interview/01-01-02-basic.html

posted @ 2023-04-28 20:47  _Explosion!  阅读(33)  评论(0编辑  收藏  举报