当前位置: 首页 > 工具软件 > Elide > 使用案例 >

g++编译优化选项-fno-elide-constructors

梁丘柏
2023-12-01

1、考虑下面的代码,请问输出结果是什么?

#include <stdio.h>

class A {
public:
	A(int val) {
		puts("A(int)");
		d = val;
	}
	A(A&& a) {
		puts("A(A&&)");
		d = a.d;
	}
	A(A& a) {
		puts("A(A&)");
		d = a.d;
	}
	~A() {}
private:
	int d;
};
A create_A(int val) {
	return A(val);
}
int main(void) {
	A a{create_A(5)};

	return 0;
}

如果你认为应该输出下面的结果,那就不用继续往下看了。

$ g++ ./main.cpp
$ ./a.out
A(int)

2、对于上面的输出结果,是不是或多或少有点出乎意料。从输出结果来看,只调用了一次构造函数,而且 移动构造函数 和 拷贝构造函数 都没有被调用。为什么会这样?是因为编译器对返回值做了优化,何以见得?我们可以打印一下create_A()中临时对象的地址,然后再打印一下main函数中对象a的地址,会发现他们是一样的。

#include <stdio.h>

class A {
public:
	A(int val) {
		puts("A(int)");
		d = val;
	}
	A(A&& a) {
		puts("A(A&&)");
		d = a.d;
	}
	A(A& a) {
		puts("A(A&)");
		d = a.d;
	}
	~A() {}
private:
	int d;
};
A create_A(int val) {
	A a(val);
	printf("create_A()::&a = %p\n", &a);
	return a;
}
int main(void) {
	A a{create_A(5)};
	printf("main()::&a = %p\n", &a);

	return 0;
}

程序运行结果如下:

$ g++ ./main.cpp
$ ./a.out
A(int)
create_A()::&a = 0x7ffee7bd08f8
main()::&a = 0x7ffee7bd08f8

3、如果开启了-fno-elide-constructors编译选项,结果就更容易理解了

$ g++ -fno-elide-constructors main.cpp
$ ./a.out
A(int)
create_A()::&a = 0x7ffee73018b8
A(A&&)
A(A&&)
main()::&a = 0x7ffee73018f8

从输出结果来看,拷贝构造函数被调用了两次,一次是create_A()内部创建的对象返回后构造一个临时对象产生的,另一次是在main函数中构造对象a产生的,同时,create_A()中对象a的地址与main函数中对象a的地址不相同。

 类似资料: