构造函数和析构函数在函数调用过程中的调用情况

一个有趣的类

我在这个类中定义了构造,拷贝构造,移动构造,拷贝运算符,移动运算符,析构,这几种特殊函数。这个类可以观察调用对象时的操作实现。

class Test {
public:
	Test(string x):str(x){
		cout << "Constructor " << str << endl;
	}
	Test(const Test& x) :str(x.str) {
		cout << "Copy Constructor " << x.str << endl;

	}
	Test(Test&& x) :str(x.str) {
		cout << "Move Constructor " << x.str << endl;
	}

	Test& operator=(const Test& x) {
		cout << "Copy-Assignment Operator " << str << endl;
		str = x.str;
		return *this;
	}
	Test& operator=(Test&& x) {
		cout << "Move-Assignment Operator " << str << endl;
		str = move(x.str);
		return *this;
	}
	~Test() {
		cout << "Destructor " << str << endl;
	}

    void address(){
		cout << "address " << this << endl;
    }
	string  str;
};

使用代码

使用该类查看函数参数和返回值的内部实现

Test f(Test c) {
	cout << "---func start---" << endl;
	Test a("a"), b("b");

	cout << "---func end---" << endl;

	return a;
}
int main() {
	cout << "---start---" << endl;
	Test c("c");
	cout << "---entry---" << endl;
	Test a=f(c);
	cout << "---break---" << endl;
	Test b = a;
	b = a;
	cout << "---end---" << endl;
	return 0;
}

输出

以下是该代码在不同编译器下的输出,建议配合着源代码和分割线观看并理解。

可以看出Microsoft C/C++ 编译器是较符合预期的,没有进行太多的优化。

test_Microsoft C/C++ :

---main start---
Constructor c               Test c("c");
---entry---
Copy Constructor c          Test tf(Test c) 拷贝构造参数c。
---func start---
Constructor a               Test a("a"), b("b");
Constructor b               构造两个对象a、b。
---func end---
Move Constructor a          Test a=tf(c) 将函数内对象a移动到main中对象a。
Destructor b                离开函数,析构局部变量,
Destructor a                这里可以看出会先返回值后,再将变量析构。
Destructor c
---break---
Copy Constructor a          Test b = a 虽然使用的是“=”但还是调用拷贝构造
Copy-Assignment Operator a  b = a 正常调用拷贝运算符
---main end---
Destructor a                离开main函数析构对象
Destructor a
Destructor c


g++ 优化了一部分内容,另外通过调用该类的 address 方法,你会发现 main 函数中的 a 对象和调用函数中的 a 对象的地址相同。

test_g++ :

---main start---
Constructor c
---entry---
Copy Constructor c
---func start---
Constructor a
Constructor b
---func end---                  其他部分都和上面相同,但这里少了个移动操作。
Destructor b
Destructor c                    这里少了给析构a的操作。
---break---                     实际上是将a的对象地址直接给了main中的a,甚至没调用移动构造
Copy Constructor a
Copy-Assignment Operator a
---main end---
Destructor a
Destructor a
Destructor c


posted @ 2022-05-19 22:17  _comet  阅读(43)  评论(0编辑  收藏  举报