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(),反过来也是可以实现的:


  • 相关阅读:
    变量的创建和初始化
    HDU 1114 Piggy-Bank (dp)
    HDU 1421 搬寝室 (dp)
    HDU 2059 龟兔赛跑 (dp)
    HDU 2571 命运 (dp)
    HDU 1574 RP问题 (dp)
    HDU 2577 How to Type (字符串处理)
    HDU 1422 重温世界杯 (dp)
    HDU 2191 珍惜现在,感恩生活 (dp)
    HH实习 acm算法部 1689
  • 原文地址:https://www.cnblogs.com/czc1999/p/10323369.html
Copyright © 2011-2022 走看看