自学内容网 自学内容网

c++构造与析构

构造函数特性

名称与类名相同:构造函数的名称必须与类名完全相同,并且不能有返回值类型(包括void)。
自动调用:构造函数在对象实例化时自动调用,不需要手动调用。
初始化成员变量:构造函数的主要作用是初始化对象的成员变量。
重载:一个类可以有多个构造函数,只要它们的参数列表不同(即构造函数可以被重载)。
无返回值:构造函数不能有返回值类型。
初始化列表:构造函数可以使用初始化列表来初始化成员变量,特别是当成员变量是常量或引用类型时

#include <iostream>
using namespace std;
 
class Point {
public:
    // 默认构造函数
    Point() {
        x = 0;
        y = 0;
        cout << "Default constructor called" << endl;
    }
 
    // 带参数的构造函数
    Point(int xVal, int yVal) {
        x = xVal;
        y = yVal;
        cout << "Parameterized constructor called" << endl;
    }
 
    void print() {
        cout << "Point(" << x << ", " << y << ")" << endl;
    }
 
private:
    int x, y;
};
 
int main() {
    Point p1; // 调用默认构造函数
    Point p2(10, 20); // 调用带参数的构造函数
 
    p1.print();
    p2.print();
 
    return 0;
}
 

继承中的调用顺序:在继承中,基类的构造函数会在派生类的构造函数之前被调用

默认构造函数: 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成

无参(默认)构造函数
有参构造函数
委托构造函数
复制(拷贝)构造函数
移动构造函数

有参,无参,拷贝三种构造函数对应三种调用方式示例

#include<iostream>
using namespace std;
class Person
{
public:
    //默认构造函数
Person();
Person()
{
cout << "调用无参(默认)构造函数" << endl;
}
Person(int a)
{
age = a;
cout << "调用有参构造函数" << endl;
}
//拷贝构造函数用于拷贝传入的类到自身类上 
//除了拷贝构造函数外都是普通构造函数
Person(const Person &p)//传入的类不希望被改变所以加const 传入引用用p指向该类
{
age = p.age;
cout << "调用拷贝构造函数" << endl;
}
~Person()
{
cout << "析构函数的调用" << endl;
}
int age;

};
void test()
{
    //调用
    //1.括号法
//注意:调用无参构造时不要输入()
//Person p();会被编译器认为是函数的声明
Person p;//调用无参构造函数
Person p1(10);//调用有参函数构造
Person p2(p1);//调用拷贝构造函数
cout <<"p1的年龄"<< p1.age << endl;
cout <<"p2的年龄"<< p2.age << endl;

//2.显式法
Person p3;//调用无参构造函数
Person p4=Person (10);//调用有参函数构造
Person p5=Person (p1);//调用拷贝构造函数
//Person(10)为匿名对象 等号左侧就是它的名 
//特点:当前行结束时,系统会立即回收掉匿名对象 即它的析构函数会在该行结束后就调用而不是test函数结束

//3.隐式转换法
Person p6 = 10; //调用有参函数构造 相当于Person p6=Person(10);  假如有两个参数就是 Person p6 = (10,9);
Person p7 = p1;//调用拷贝构造函数 相当于Person p7=Person(p1);
}
int main()
{
test();
system("pause");
return 0;
}

#include<iostream>
using namespace std;
class Person
{
public:
//默认构造函数
Person();
//有参构造
Person(int age, int height);
int m_Age;
int* m_Height;
};
//默认构造
Person::Person() 
{
cout << "默认构造函数的调用!" << endl;
this->m_Age = 0;
this->m_Height = new int(0);
}
//有参构造,把age赋值给m_Age,身高用m_Height指向
Person::Person(int age,int height)
{
cout << "有参构造函数的调用!" << endl;
this->m_Age = age;
this->m_Height = new int(height);
}
int main()
{
Person p(18,175);
cout << "此人的年龄是: " << p.m_Age << endl;
cout << "此人的身高是: " << *(p.m_Height) << endl;
return 0;
}


委托构造函数

委托构造函数就是把自己构造的事情,交给其他的构造函数顺带完成

#include<iostream>
using namespace std;
class Person
{
public:
//默认构造函数
Person();
//有参构造
Person(int age, int height);
//拷贝构造
Person(const Person& p);
int m_Age;
int* m_Height;
};
//默认构造
Person::Person() :Person(0, 0)
{
cout << "委托构造函数的调用!" << endl;
}
//有参构造,把age赋值给m_Age,身高用m_Height指向
Person::Person(int age, int height)
{
cout << "有参构造函数的调用!" << endl;
this->m_Age = age;
this->m_Height = new int(height);
}
//拷贝构造函数调用
Person::Person(const Person& p)
{
cout << "拷贝构造函数的调用!" << endl;
this->m_Age = p.m_Age;
this->m_Height = new int(*p.m_Height);
}
int main()
{
Person p;
cout << "p的年龄是: " << p.m_Age << endl;
cout << "p的身高是: " << *(p.m_Height) << endl;
return 0;
}
#include<iostream>
using namespace std;
class Person
{
public:
//默认构造函数
Person();
//有参构造
Person(int age, int height);
//拷贝构造
Person(const Person& p);
int m_Age;
int* m_Height;
};
//默认构造
Person::Person()
{
cout << "默认构造函数的调用!" << endl;
this->m_Age = 0;
this->m_Height = new int(0);
}
//有参构造,把age赋值给m_Age,身高用m_Height指向
Person::Person(int age, int height)
{
cout << "有参构造函数的调用!" << endl;
this->m_Age = age;
this->m_Height = new int(height);
}
//拷贝构造函数调用
Person::Person(const Person& p)
{
cout << "拷贝构造函数的调用!" << endl;
this->m_Age = p.m_Age;
this->m_Height = new int(*p.m_Height);
}
int main()
{
Person p1(18, 175);
cout << "p1的年龄是: " << p1.m_Age << endl;
cout << "p1的身高是: " << *(p1.m_Height) << endl;
Person p2(p1);//将对象p1复制给p2。注意复制和赋值的概念不同 
cout << "p2的年龄是: " << p2.m_Age << endl;
cout << "p2的身高是: " << *(p2.m_Height) << endl;
return 0;
}

#include<iostream>
#include<string>
using namespace std;
class Point {
public:
    Point(int a,int b,int c)
    {
        this->a = a;
        this->b = b;
        this->c = c;
        cout << "这是Pointd的有3个默认参数的构造函数!  "<<this->a<<" "<<this->b<<" "<<this->c<<endl;
    }

    Point(int a, int b)
    {
        this-> a= a;
        this->b = b;
        Point(3, 4, 5);//产生一个匿名对象,纸条语句执行结束,匿名对象会被析构。
        cout << "这是Pointd的有2个默认参数的构造函数!  " << this->a << " " << this->b << endl;
    }
    ~Point()
    {
        cout << "Point对象被析构了! "<<this->a << " " << this->b << " " << this->c << endl;
    }

    int getC()
    {
        return c;
    }
private:
    int a;
    int b;
    int c;

};


int run()
{
    Point aa(1, 2);
    cout << aa.getC() << endl;  //c的值为垃圾值,因为匿名对象被创建有立即析构了  
//就算用不析构的方式,也是垃圾值,因为c是不同对象中的元素     
                   //在2个参数的构造函数中,没有显式初始化c,不能通过构造其他对象而在本构造对象中访问未初始化的数据
    return 0;
}
int main()
{
    
    run();
    cout << "hello world!\n";
    return 0;
}

C++之构造函数的初始化参数表

初始化列表是成员变量定义的地方
不管有没有显示写初始化参数列表,编译器在调用构造函数时都会先走初始化参数列表
在C++11新特性中,允许在类中声明变量时给上缺省值,这里的缺省值实际上是给初始化参数列表使用的
初始化参数列表初始化的顺序与成员函数的声明顺序一致

class A{
public:
    //在函数的括号后使用 : 成员变量(参数) 使用逗号进行分割
//A(int a,int b):x(a),y(b){}
    A(int a,int b)
        : x(a)
        , y(b)
     {}
private:
int x;
int y;
};
struct Test1
{
    Test1() // 无参构造函数
    { 
        cout << "Construct Test1" << endl ;
    }

    Test1(const Test1& t1) // 拷贝构造函数
    {
        cout << "Copy constructor for Test1" << endl ;
        this->a = t1.a ;
    }

    Test1& operator = (const Test1& t1) // 赋值运算符
    {
        cout << "assignment for Test1" << endl ;
        this->a = t1.a ;
        return *this;
    }

    int a ;
};

struct Test2
{
    Test1 test1 ;
    Test2(Test1 &t1)
    {
        test1 = t1 ;
    }
};

常用构造:
Test1() // 无参构造函数
A(int a,int b):x(a),y(b){}//构造函数初始化参数表
Test1(const Test1& t1) // 拷贝构造函数
Test1& operator = (const Test1& t1) // 赋值运算符

初始化列表实例

class Stack {
public:
Stack(int capacity = 10): _a((int*)malloc(sizeof(int))), _top(0), _capacity(capacity)
{
if (nullptr == _a)
{
perror("fail malloc");
exit(-1);
}
memset(_a, 0, sizeof(int) * capacity);
}
private:
int* _a;
int _top;
int _capacity;
};
class A {
public:
A():_x(1),_a1(3),_a2(1),_z(_a1)
{
_a1++;
_a2--;
}
private:
int _a1 = 1;//声明
int _a2 = 2;

const int _x;
int& _z;
B _bb;
};


析构函数

清理资源:析构函数通常用于释放对象在其生命周期内分配的资源,例如动态分配的内存、打开的文件句柄等

#include <iostream>
using namespace std;
 
class Example {
public:
    // 构造函数
    Example() {
        cout << "Constructor called" << endl;
        data = new int[10]; // 动态分配内存
    }
 
    // 析构函数
    ~Example() {
        cout << "Destructor called" << endl;
        delete[] data; // 释放动态分配的内存
    }
 
private:
    int* data;
};
 
int main() {
    Example ex; // 创建对象,调用构造函数
    // 对象生命周期结束时,自动调用析构函数
    return 0;
}


#include <iostream>
using namespace std;
//构造函数的实现
class Student
{
public:     //:flag(Flag)解释:类内变量(参数)
  Student(int Flag,char Sex, string Name, const char *File); //类外参数列表函数声明
  

  //类内使用方式,不需要声明
  // Student(int Flag,char Sex, string Name) :flag(Flag),sex(Sex),name(Name) //构造函数
  // {
  //   // //错误形式:
  //   // int a=10;
  //   // int &b;
  //   // b=a; //大错特错
  //   cout<<"类内:flag="<<this->flag<<endl;
  //   cout<<"类内:sex="<<this->sex<<endl;
  //   cout<<"类内:name="<<this->name<<endl;
  // }

private:
  int &flag;  //必须用参数列表方式
  char sex;
  string name;
  const char *file = NULL;  //必须使用参数列表方式
  //引用变量定义法则->构造函数名(参数):引用变量名(参数)

};

//类外构造函数
Student::Student(int Flag,char Sex, string Name,const char *File):flag(Flag),sex(Sex),name(Name),file(File) //构造函数
  {
    // //错误形式:
    // this->flag=Flag;相当于以下:
    // int a=10;
    // int &b;
    // b=a; //大错特错
    cout<<"类内:flag="<<this->flag<<endl;
    cout<<"类内:sex="<<this->sex<<endl;
    cout<<"类内:name="<<this->name<<endl;
    cout<<"类内:file="<<this->file<<endl;
  }
int main(int argc, char const *argv[])
{
  Student st(100,'M',"JKJK","/usr/include/linux/fb.h");  //先创建了对象,后执行构造函数
  return 0;
}

struct foo
{
    int i ;
    int j ;
    foo(int x):i(x), j(i){}; // ok, 先初始化i,后初始化j
};

浅拷贝

int* shallowCopy(int* original) {
    return original; // 只是复制了指针,没有复制指针指向的内存
}

浅拷贝只是复制了对象的引用或指针,而不是复制对象所指向的资源

深拷贝

int* deepCopy(int* original, size_t size) {
    int* copy = new int[size];
    std::copy(original, original + size, copy);
    return copy; // 复制了指针指向的内存
}
class MyArray {
public:
    MyArray(size_t size) : size_(size), data_(new int[size]) {}
    ~MyArray() { delete[] data_; }// 禁用拷贝构造函数和赋值操作符以防止浅拷贝
    MyArray(const MyArray&) = delete;
    MyArray& operator=(const MyArray&) = delete;// 实现深拷贝的拷贝构造函数
    MyArray(const MyArray& other) : size_(other.size_), data_(new int[other.size_]) {
        std::copy(other.data_, other.data_ + size_, data_);
    }// 实现深拷贝的赋值操作符
    MyArray& operator=(MyArray other) {
        std::swap(size_, other.size_);
        std::swap(data_, other.data_);
        return *this;
    }
​
private:
    size_t size_;
    int* data_;
};

有时间继续


原文地址:https://blog.csdn.net/weixin_44245323/article/details/143655466

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!