zoukankan      html  css  js  c++  java
  • C/C++——赋值理解(匿名临时对象)

    对三,王炸:

    赋值的本质,是将变量传递给一个匿名临时变量,之后再传递给另一个变量。


    •  匿名临时对象:
    #include <iostream>
    using namespace std;
    
    class A {
    public:
        A() {
            cout << "构造函数:" << this << endl;
        }
        A(const A &a) {
            cout << "拷贝构造函数:" << this << endl;
        }
        ~A() {
            cout << "析构函数:" << this << endl;
        }
    };
    
    A f() {
        A a;
        return a;
    }
    int main() {
        A a = f();
        return 0;
    }

    首先要知道赋值的时候回调用拷贝构造函数,初始化的时候调用构造函数:

    执行 return a; 产生了匿名临时对象 F903,在给a(外面的)的赋值之前,销毁局部对象F803,F903赋值给了外面的a,程序执行结束时销毁。

     

     A()用来创建匿名对象,理论上这也是应该调用拷贝构造函数的,但事实上,编译器会对此进行优化,变成A a;

     那么怎样能避免产生临时对象呢?

    直接赋值是不可避免的,但是作为函数返回值时是可以避免的:

     当返回类型为引用是,在内存中不产生返回值的副本(注意:不能返回局部变量的引用,局部变量会在函数之前销毁。)

    对于这个例子,左边的return ,实际上是调用拷贝构造函数把该对象的值拷入临时对象,再进行return,
    return完毕临时对象即刻销毁。对于一般变量亦是如此,只是不调用构造函数。

    注意:
    • 不要返回函数内部new分配的内存的引用:

    正常写法,无内存泄漏。

    被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,显然new生成的这块内存将无法释放。

    (和上面说的不矛盾,这里直接把*s返回了,不再需要额外的一个临时变量了,但是外面的string s; 已经在栈中分配内存了。)

     

     想要释放掉这片内存,只能这样:

    所以说,并不是说返回函数内存new分配的内存的引用或指针是非法的,只是说如果要返回,必须要十分注意,因为很有可能造成内存泄露。
    所以一般不提倡返回函数内存new分配的内存的引用或指针。

    •   强制类型转化:

    C++属于强类型语言,只要类型不一样,就不能赋值。

    但是这里是可以赋值当场打脸,也是因为出现了一个匿名临时对象作为隐式转换的过渡桥梁。

        

    注意第二张图:

    这里并不是&b开辟了新的空间,引用的就是转换的临时变量

    (int &b = a;是报错的)可见临时变量的常量性,const才能引用。

    下面这样的隐式转换看似好像是错的。

    #include <iostream>
    using namespace std;
    
    class A {
        
    public:
        int x;
        A(int num) {
            cout << "构造函数:" << this << endl;
            x = num;
        }
        A(const A &a) {
            cout << "拷贝构造函数:" << this << endl;
        }
        ~A() {
            cout << "析构函数:" << this << endl;
        }
    };
    
    int main() {
        A a = 10;
        cout << a.x << endl;
        return 0;
    }

     两个不同类型能否进行赋值操作,在于能否找到一个中间桥梁,这里的赋值寻找到了构造函数A(int num){};(重载 ‘=’ 运算符也是可以实现的) 所以可以成功,并且a成功实例化。

     在构造函数前加上explicit关键字,则禁止 类似这样 不应该允许的经过转换构造函数进行的隐式转换的发生。

    加上一个operator int(),反过来也是可以实现的:


  • 相关阅读:
    bat脚本运行py文件失败(一闪而过)
    python 将日期戳(五位数时间)转换为标准时间
    Pandas 如何通过获取双(多)重索引获取指定行DataFrame数据
    Pandas 横向合并DataFrame数据
    Pandas 删除指定列中为NaN的行
    git 解决push报错:[rejected] master -> master (fetch first) error: failed to push some refs to
    pandas删除包含指定内容的行
    python项目环境的导出、导入
    pandas 修改列名
    Javascript 异步编程的4种方法
  • 原文地址:https://www.cnblogs.com/czc1999/p/10323369.html
Copyright © 2011-2022 走看看