天天看點

C++函數傳回值的規則

C++函數傳回值的規則

  1. 【規則6-2-1】不要省略傳回值的類型。

C語言中,凡不加類型說明的函數,一律自動按整型處理。這樣做不會有什麼好處,卻容易被誤解為void類型。

C++語言有很嚴格的類型安全檢查,不允許上述情況發生。由于C++程式可以調用C函數,為了避免混亂,規定任何C++/ C函數都必須有類型。如果函數沒有傳回值,那麼應聲明為void類型。

  1. 【規則6-2-2】函數名字與傳回值類型在語義上不可沖突。

違反這條規則的典型代表是C标準庫函數getchar。

例如:

char c;

c = getchar();

if (c == EOF)

按照getchar名字的意思,将變量c聲明為char類型是很自然的事情。但不幸的是getchar的确不是char類型,而是int類型,其原型如下:

        int getchar(void);

由于c是char類型,取值範圍是[-128,127],如果宏EOF的值在char的取值範圍之外,那麼if語句将總是失敗,這種“危險”人們一般哪裡料得到!導緻本例錯誤的責任并不在使用者,是函數getchar誤導了使用者。

  1. 【規則6-2-3】不要将正常值和錯誤标志混在一起傳回。正常值用輸出參數獲得,而錯誤标志用return語句傳回。

回顧上例,C标準庫函數的設計者為什麼要将getchar聲明為令人迷糊的int類型呢?他會那麼傻嗎?

在正常情況下,getchar的确傳回單個字元。但如果getchar碰到檔案結束标志或發生讀錯誤,它必須傳回一個标志EOF。為了差別于正常的字元,隻好将EOF定義為負數(通常為負1)。是以函數getchar就成了int類型。

我們在實際工作中,經常會碰到上述令人為難的問題。為了避免出現誤解,我們應該将正常值和錯誤标志分開。即:正常值用輸出參數獲得,而錯誤标志用return語句傳回。

函數getchar可以改寫成 BOOL GetChar(char *c);

雖然gechar比GetChar靈活,例如 putchar(getchar()); 但是如果getchar用錯了,它的靈活性又有什麼用呢?

  • 【建議6-2-1】有時候函數原本不需要傳回值,但為了增加靈活性如支援鍊式表達,可以附加傳回值。

例如字元串拷貝函數strcpy的原型:

char *strcpy(char *strDest,const char *strSrc);

strcpy函數将strSrc拷貝至輸出參數strDest中,同時函數的傳回值又是strDest。這樣做并非多此一舉,可以獲得如下靈活性:

    char str[20];

    int  length = strlen( strcpy(str, “Hello World”) );

  • 【建議6-2-2】如果函數的傳回值是一個對象,有些場合用“引用傳遞”替換“值傳遞”可以提高效率。而有些場合隻能用“值傳遞”而不能用“引用傳遞”,否則會出錯。

例如:

class String

{…

    // 指派函數

    String & operate=(const String &other);

// 相加函數,如果沒有friend修飾則隻許有一個右側參數

friend  String   operate+( const String &s1, const String &s2);

private:

    char *m_data;

}

       String的指派函數operate = 的實作如下:

String & String::operate=(const String &other)

{

    if (this == &other)

        return *this;

    delete m_data;

    m_data = new char[strlen(other.data)+1];

    strcpy(m_data, other.data);

    return *this;   // 傳回的是 *this的引用,無需拷貝過程

}

對于指派函數,應當用“引用傳遞”的方式傳回String對象。如果用“值傳遞”的方式,雖然功能仍然正确,但由于return語句要把 *this拷貝到儲存傳回值的外部存儲單元之中,增加了不必要的開銷,降低了指派函數的效率。例如:

  String a,b,c;

  …

  a = b;      // 如果用“值傳遞”,将産生一次 *this 拷貝

  a = b = c; // 如果用“值傳遞”,将産生兩次 *this 拷貝

       String的相加函數operate + 的實作如下:

String  operate+(const String &s1, const String &s2) 

{

    String temp;

    delete temp.data;   // temp.data是僅含‘\0’的字元串

        temp.data = new char[strlen(s1.data) + strlen(s2.data) +1];

        strcpy(temp.data, s1.data);

        strcat(temp.data, s2.data);

        return temp;

    }

對于相加函數,應當用“值傳遞”的方式傳回String對象。如果改用“引用傳遞”,那麼函數傳回值是一個指向局部對象temp的“引用”。由于temp在函數結束時被自動銷毀,将導緻傳回的“引用”無效。例如:

    c = a + b;

此時 a + b 并不傳回期望值,c什麼也得不到,流下了隐患。

繼續閱讀