C++对象模型(16)-- 构造函数语义学:临时对象

临时对象是栈上的没有名字的对象,它在源码中是不可见的,是编译器偷偷摸摸在背后干的。

比如下面的代码就会产生临时对象:

int i = 1;

// 这里的 i++ 会产生临时对象,这里的临时对象是在系统中产生,代码中看不见的
// 首先将i的值赋给临时对象,再把临时对象的值作为返回结果赋给j,再对i进行自增操作。
int j = i++;

临时对象有以下几个特点:

(1)临时对象是在栈上生成的。

(2)临时对象是右值,可通过“const 左值引用”绑定临时对象,或通过右值绑定临时对象。

(3)临时对象的产生和销毁会调用1次构造函数和析构函数。

临时对象的产生和销毁需要消耗系统资源,所以在写代码时应尽量避免临时对象的产生。

1、临时对象的产生及解决办法

临时对象主要产生在下列场景中:

(1)在栈中生成无名对象时

Integer objI = Integer(1);

先产生一个Integer临时对象,然后调用拷贝构造函数生成objI对象。

解决办法:在定义时直接初始化。

Integer objI(1);
Integer objI{1};

(2)类型转换

class MyDemo {
public:
    MyDemo(){}

    MyDemo(int i) {
        std::cout << "构造函数MyDemo(int i)" << std::endl;
    }

    MyDemo& operator = (const MyDemo& _demo) {
        std::cout << "赋值运算符" << std::endl;
        
        return *this;
    }

    ~MyDemo() {
        std::cout << "析构函数" << std::endl;
    }
};

int main()
{

    MyDemo demo;
    demo = 100;

    return 0;
}

这里的demo = 100,会产生临时对象:

(1)将 100为参数调用了MyDemo的构造函数创建了一个临时对象;

(2)通过拷贝赋值运算符,将临时对象的成员值赋给了demo;

(3)销毁临时对象。

解决办法:创建对象时进行初始化。

MyDemo demo = 100;

(3)隐式类型转换

void testFunc(const MyDemo& demo) {}

int main()
{
    int i = 2;
    testFunc(i);
    
    return 0;
}

上面的testFunc(i),会产生临时对象。int值会先转换成MyDemo类型的临时对象,然后赋值给形参demo。

解决办法:

将传入的实参和函数的形参类型保持一致即可:

testFunc(MyDemo(i));

(4)函数参数

函数的参数传值是值传递,在函数调用时系统会创建一个临时对象。

class MyDemo {
public:
    MyDemo() {}

    MyDemo(int i) {
        std::cout << " 构造函数MyDemo(int i)" << std::endl;
    }

    MyDemo(const MyDemo& _demo) {
        std::cout << " 拷贝构造函数" << std::endl;
    }

    ~MyDemo() {
        std::cout << " 析构函数" << std::endl;
    }
};

void testFunc(MyDemo demo) {
    std::cout << " testFunc" << std::endl;
}

int main()
{
    MyDemo demo;
    testFunc(demo);
    
    return 0;
}

从执行结果可以看到,在调用testFunc()函数时,指向了拷贝构造函数。

解决办法:把值传递改成引用传递。

void testFunc(MyDemo& demo) {}

(5)函数返回值

在函数返回对象时候,会创建一个临时对象接收这个对象;从而调用了拷贝构造函数,和析构函数。

MyDemo testFunc() {
    MyDemo demo;

    return demo;
}

int main()
{
    MyDemo demo = testFunc();

    return 0;
}

解决办法:

(1)修改testFunc的形参,把返回对象作为形参传入函数。

MyDemo testFunc(MyDemo& ret) {}

(2)用右值接收返回值

MyDemo&& d = testFunc();

你可能感兴趣的:(C++对象模型,c++,对象模型,临时对象)