程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++返回值為對象時復制構造函數不執行怎麼破

C++返回值為對象時復制構造函數不執行怎麼破

編輯:C++入門知識

C++返回值為對象時復制構造函數不執行怎麼破


  先說點背景知識,調用復制構造函數的三種情況:

  1.當用類一個對象去初始化另一個對象時。

  2.如果函數形參是類對象。

  3.如果函數返回值是類對象,函數執行完成返回調用時。

  在輔導學生上機時,有同學第3點提出異議。有教材上的例題為證:

#include 
using namespace std;
class Point     //Point 類的定義
{
public:
    Point(int xx=0, int yy=0)
    {
        x = xx;    //構造函數,內聯
        y = yy;
    }
    Point(const Point& p); //復制構造函數
    void setX(int xx)
    {
        x=xx;
    }
    void setY(int yy)
    {
        y=yy;
    }
    int getX() const
    {
        return x;    //常函數(第5章)
    }
    int getY() const
    {
        return y;    //常函數(第5章)
    }
private:
    int x, y; //私有數據
};
//成員函數的實現
Point::Point (const Point& p)
{
    x = p.x;
    y = p.y;
    cout << "Calling the copy constructor " << endl;
}

//形參為Point類對象的函數
void fun1(Point p)
{
    cout << p.getX() << endl;
}
//返回值為Point類對象的函數
Point fun2()
{
    Point a(1, 2);
    return a;
}

//主程序
int main()
{
    Point a(4, 5);	//第一個對象A
    Point b = a;	//情況一,用A初始化B。第一次調用復制構造函數
    cout << b.getX() << endl;
    fun1(b);	//情況二,對象B作為fun1的實參。第二次調用復制構造函數
    b = fun2();	//情況三,函數的返回值是類對象,函數返回時調用復制構造函數
    cout << b.getX() << endl;
    return 0;
}
  證據是,在CodeBlocks中,運行結果是:

 

  \

  而不是期望的:
  \

  顯然,第3種情況下,復制構造函數沒有被執行。

  確定問題後,我知道道理是對的,看過的幾本書,厚的、薄的,都是這麼寫的。會不會是編譯器的差別?CodeBlocks用的是gcc。gcc開源,跟標准的變化跟得緊,莫不是第3種情況已經成了老黃歷,而各種書來不及變?

  我讓她到VC++6.0中運行。一會兒她的反饋,在VC++6.0中復制構造函數執行了。

  真相明白了。

  這個問題需要有個交待。

  回家後再翻各種書,無果。網絡搜索,CSDN上有個貼子《函數返回值是對象,是調用了拷貝構造函數?》,其中大家給的結論,是gcc做了優化,返回值為對象時,不再產生臨時對象,因而不再調用復制構造函數。

  看來不是標准發生變化。

  那如果一定想要讓這個構造函數執行呢?只需讓忽略gcc不要搞這個優化就行了。貼子中給了個線索,在新浪博客《命名返回值優化》。文章稱通過搜索知道“這是一個稱為命名返回值優化的問題,而且g++的這個編譯優化竟然沒有直接的關閉方法給出解決辦法”。作者是用命令行工作的,他後來解決的辦法,是在編譯命令中加上“-fno-elide-constructors”參數,例g++ -fno-elide-constructors testReturn.cpp。

  我的學生還處在用IDE的階段。本文的價值來了,如何在CodeBlocks下也忽略這個優化項呢?

  在CodeBlocks中,通過菜單依次選:settings->Compiler...,在Global compiler settings部分,選擇Other options,在文本框中寫入“-fno-elide-constructors”,如圖,然後就可以ok啦。

  \

  然後,如同苦難的公主終於和王子過上了幸福的生活一樣,期望的結果有了。

  \

  “-fno-elide-constructors”選項起了作用,有圖為證。下面中加上這個參數後,編譯完看到的提示信息:

\

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved