c++的命名返回值優化問題

背景知識

copy構造函數在以下三種情況下會調用:

  • 對象初始化
  • 函數形參值傳遞
  • 返回局部對象

問題引出

看c++運算符重載時碰到一個問題,代碼如下,文件名爲operatorTest.cpp,重點看看operqtor+這個函數。

# include <iostream>
using namespace std;

class demo
{
private:
	int a;
	int b;
public:
	demo(int a = 0, int b = 0)
	{
		cout << "constructor..." << endl;
		this->a = a;
		this->b = b;
	}
	demo (const demo & d)
	{
		cout << "copy constructor..." << endl;
		this->a = d.a;
		this->b = d.b;
	}
	demo operator + (demo & another)
	{
		demo d(this->a + another.a, this->b + another.b);
		return d;
	}
	void print()
	{
		cout << "a : " << a << "b : " << b << endl;
	}
};

int main (void)
{
	demo a(1,2), b(3,4);
	demo c;
	c = a + b;
	c.print();
	return 0;
}

可以看到 operator+ 這個函數返回了一個局部對象,根據copy構造函數的調用時機可知,copy構造函數這時候應該會調用,我在終端輸入

feilei /Users/feilei/repos/workspace/cpp $ g++ operatorTest.cpp -o operatorTest
feilei /Users/feilei/repos/workspace/cpp $ ./operatorTest

編譯執行operatorTest.cpp時結果如下

constructor...
constructor...
constructor...
constructor...
a : 4b : 6

可以看出,並未調用copy構造函數。問題就是這樣,根據copy函數的調用規則,應該有copy構造函數調用,但是實際上並沒有。

問題解決

一番搜索之後,發現這個問題早已經有人提出並且得到了解決方案。答案是:gcc編譯器做了優化,因爲那一次copy函數調用並不是必要的。gcc和g++千絲萬縷的聯繫可以參見這個:gcc和g++是什麼關係?

如何要忽略編譯器做的優化,可以採用如下命令:

feilei /Users/feilei/repos/workspace/cpp $ g++ -fno-elide-constructors operatorTest.cpp -o operatorTest
feilei /Users/feilei/repos/workspace/cpp $ ./operatorTest

編譯結果如下:

constructor...
constructor...
constructor...
constructor...
copy constructor...
a : 4b : 6

reference

C++函數返回局部變量對象的優化-不調用複製構造函數
命名返回值優化
急急急! 求大神啊。 函數返回值是對象,是調用了拷貝構造函數?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章