首页 > 编程语言 >C++ 构造函数和析构函数

C++ 构造函数和析构函数

时间:2023-03-15 17:34:18浏览次数:34  
标签:初始化 const 对象 构造 C++ 拷贝 和析构 构造函数

构造函数和析构函数

目录

页面

构造/和析构函数


问题

编译器为什么要求拷贝构造为什么要传引用?

如果存在两个 同类型的对象A a, b ,如果将a 拷贝给 b ,实际上call b类的拷贝构造,b对象的拷贝对象是如果是非引用形式。以 a() 实参, (A const A a)形参 ,这时是同一类型,他又回去call 形参的拷贝构造,形参还是(A const A a)形参 ,实参又去形参的拷贝构造 ,套娃。。。

Int & 不能拷贝给匿名对象上的

为什么要const A &a (45 被bind 后是没有绑定匿名对象上的,const 是为兼容bind 到匿名对象的 )

做一个逻辑上的常量限制。(从逻辑上是不允许被拷贝对象被修改的)

兼容const类型的拷贝 不允许直接吧const 类型的变量直接传到址非const的引用, 因为非const 是可以修改的。


构造函数与析构函数

构造/和析构函数 使用方式
默认构造函数 ostream a;
ostream(string name ) ostream a(xx)
ostream (const ostream &a) 拷贝构造 于 = 不等价
~ostream 无 析构

每个对象创建时,一定call 构造函数,当然销毁也一定会调析构。


class Data{
public :
    Data() {
        cout << "default " << endl;
    }   
    int  x(){return __x;}; 
    int  y(){return __y;};

    ~Data(){
        cout  << "Free" <<endl;
    }   
private :
    int __x,__y;
};

int main(){
    Data dt; 
    cout <<dt.x() << dt.y() <<endl;                                                
    return 0;
}
// outoput 
//default 
//41969760
//Free

初始化列表

(初始化类中的成员)

初始化列表的顺序,和类中属性,声明的顺序有关系。而不是由初始化列表的顺序决定

最终的意义就是→初始化每一个属性的行为。

按照约定,如果构造函数初始化完成所有的初始化列表 ,意味每个成员对象的属性已经初始化结束。

class A{
public :
    A(){} // 一旦有带参数的构造器,如果没有调用按照规则调用构造函数的参树,则会报错 
    A(int x):x(x){
        cout << "Class A:" << x  <<endl;
    }   
    int x ; 
};

class Data{
public :
    // 接在构造函数后面  : 初始列表(初始化成员)
    //显示性的调用 A的构造函数
    Data():__x(10),__y(0),a(34) {
        cout << "default " << endl;
    }   
    int  x(){return __x;}; 
    int  y(){return __y;};

    ~Data(){
        cout  << "Free" <<endl;
    }   
private :                                                                          
    int __x,__y;
    A a;
};

转换构造

一个参数构造函数又转换构造

这个赋值运算可以看做 将int转到A类型的对象,整形转换为一个A类型的对象.

class A{
  public :
      A(){} // 一旦有带参数的构造器,如果没有调用按照规则调用构造函数的参树,则会报错 需要显示指出构>      A(int x):x(x){
          cout << "Class A:" << x  <<endl;
      } 
      int x ;
 };
 int main(
   A s(45);   
   A x =41; 
   return
 )
 
//0x7fff1a506a40  Class A:45
// addressof a :0x7fff1a506a40

拷贝构造(这种都是浅拷贝,每一项成员依次拷贝过去)

系统会自动添加拷贝构造,即使没有声明拷贝构造.在调用时,也会依次调用

☕g++ -fno-elide-constructors 构造函数返回值优化 编译时需要带上参数才能编译出


class A{
public :
    A(){
        cout << " default" << endl;
    } // 一旦有带参数的构造器,如果没有调用按照规则调用构造函数的参树,则会报错 需要显示指出构造函数
    A(int x):x(x){
        cout << this << "  Class A:" << x  <<endl;
    }   
    A(const A &a){
        //拷贝构造
        cout << this << "   :copy A" << &a <<endl; 
    }   
    int x ; 
};

 A a=45;
 cout << "addressof a :" <<  &a <<endl;

0x7ffcfaaf6380  Class A:45
0x7ffcfaaf6370   :copy  from A0x7ffcfaaf6380
addressof a :0x7ffcfaaf6370

第一行:调用为6380 的有参构造 ,这个小a的地址为 6370,也就是说这个0x7ffcfaaf6380 并非调的小a的有参构造

第二行,在调用第一行的有参构造函数后,第二行也会默认执行拷贝构造 ,将f6370拷贝给小a

☕首先这个**45 **会通过转换构造 去转换成一个匿名对象,匿名的对象为这个f6380对象,然后再将匿名的a对象拷贝6370对象

默认的赋值运算符

当赋值运算符出现的时候,起始出现的是拷贝构造 ,因为 这个a 还没声明好,所以使用的是拷贝构造,

而下面的而赋值运算符在赋值时,a 对象已经准备好了

class A{
public :
    A(){
        cout << " default" << endl;
    } // 一旦有带参数的构造器,如果没有调用按照规则调用构造函数的参树,则会报错 需要显示指出构造函数
    A(int x):x(x){
        cout << this << "  Class A:" << x  << endl;
    } 
    A(const A &a){
        //拷贝构造
        cout << this << "   :copy A" << &a << endl; 
    }
    void operator=(const A &a){
        cout << this << "assign from " << &a << endl;
    }
    int x ;
};
0x7ffef092db80  Class A:45
0x7ffef092db70   :copy from  A0x7ffef092db80
addressof a :0x7ffef092db70
0x7ffef092db90  Class A:78
0x7ffef092db70   assign from 0x7ffef092db90

int main(){
   A a = 45;
   cout << "addressof a :" <<  &a <<endl;
   a  =  78 ; //这个= 是相当于是call赋值运算符
   return 0;
 }


db80 通过转换构造 构造的对象 db90 也通过转换构造 构造的对象 (匿名的对象)

这个a的对象为 db70 通过 db80 拷贝过来 || 而这个db90 是通过赋值运算符赋值给 db70的

小的总结

A a = 78 由于这里的等号 ,一定call 调了拷贝构造 (而拷贝的出现的形式,是用的A类型的引用,这时会将45的参数(它本就不是a类型的值). 这时会通过转换构造,将45转换为匿名的临时对象,然后绑定到这个const A &a 的引用上)

a = 78 ; //这里就很明显,就调了 赋值运算符 (const A &a),后续过程一致。

标签:初始化,const,对象,构造,C++,拷贝,和析构,构造函数
From: https://www.cnblogs.com/yijieyufu/p/17219321.html

相关文章

  • C++ 常用语法
    1.定义一个字符串常量staticconststd::stringversion("0.0.1");staticconststd::stringname("Car-"+version);2.定义size大小staticconstexpruint64_tsh......
  • C++风格 字符串操作
    获取字符串长度              str.size();或者str.length();连接字符串                     str=str+"world";删除字符串......
  • [计算机基础笔记] C/C++
    C语言面向过程,C++面向对象。面相过程的思维方式,它更加注重这个事情的每一个步骤以及顺序。他比较直接高效,需要做什么可以直接开始干。程序=算法+数据面向对象的思维方式......
  • C++学习笔记3
    18.虚析构问题提出:在继承关系中构造和析构什么时候被调用?假如当前有类CSon继承CFather构造:当newCSon的时候,就会调用CSon(),程序跳进CSon(),在CSon()里会先调用CFather(......
  • C++学习笔记4
    C++=C+面向对象+泛型编程+STL26.STL容器STL(标准模板库),它其中包含了:容器、迭代器、算法、空间配置器、配接器、仿函数六个部分,这里介绍一些容器以及几个简单算法......
  • 一些不常遇到的C++知识总结
    explicit防止隐式转换C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生,声明为explicit的构造函数不能在隐式转换中使用。C++中,一个......
  • 机试 C语言C++字符串知识
    机试中对于字符串而言有两种风格的字符串C语言风格C++风格其中输入和输出最好使用C语言风格的字符串 本质上是数组。即字符数组。对字符串的操作最好使用C++语言......
  • C++学习笔记1
    0.初识C++我们可以视C++为一个语言联邦,在C++中包含了这样几大块:C语言(以C语言为基础)、Object-OrientedC++(面向对象)、TemplateC++(泛型编程)、STL(标准模板库)1.C+......
  • C++学习笔记2
    @目录15.const和static在类中的应用const在类中的应用(1):在类当中定义一个常量成员const在类中的应用(2):在类当中定义一个常函数const在类中的应用(3):常量类static在类中的应用(1):......
  • 思考(C++)
    为什么C++类中成员访问修饰符是private、protected、public三种而不是别的?面向对象的三大特征是:封装,继承和多态封装是指隐藏对象的属性和实现细节,仅对外公开接口使得使用......