2012-11-01 63 views
3

當函數將非const參數作爲參數時,它可能會創建難以讀取的代碼,因爲在調用站點上,哪些輸入可能會更改並不明顯。這導致一些代碼約定來執行的指針來代替,例如使用boost :: ref來指示編碼約定中的意圖

void func(int input, int* output); 

int input = 1, output = 0; 
func(input, &output); 

代替

void func(int input, int& output); 

int input = 1, output = 0; 
func(input, output); 

就個人而言,我不喜歡用,因爲需要檢查空指針。這導致我懷疑的boost :: REF(或std ::裁判對C++ 11)可用於信號意向,具體如下:

void func(int input, int& output); 

int input = 1, output = 0; 
func(input, boost::ref(output)); 

這將被用來作爲一個公司編碼約定。 我的問題是,有沒有任何理由爲什麼這不是一個好主意?

+1

我真的不想避免非const引用,因爲您需要查看函數的聲明,以確保您正確調用它(正確的參數數,正確的類型)。我沒有看看你的想法是一個壞主意的任何原因,但我認爲從長遠來看,這不會給你帶來太多的收益。 – bstamour

回答

1

本公司編碼約定可以很容易地(按課程的錯誤)打破這樣的:

void func(int input, int& output); 

int input = 1, output = 0; 
func(boost::ref(input), output); 

此編譯和工作正常 - 但在誤導讀者。

更好的是讓FUNC好名字,這表明一些參數都在上面修改:

void copyTo(int input, int& output); 

在現代的IDE - 你可以看到在閱讀什麼功能正在做什麼。


也許更好的公司會在相反的方式,通過使用boost :: CREF編碼約定:

void func(int input, int& output); 

int input = 1, output = 0; 
func(boost::cref(input), output); 

這裏犯錯像的boost ::裁判是不可能的......

3

這是這不是一個壞主意,但它並沒有真正實施(正如PiotrNycz所指出的那樣)。這實際上只是一個評論。

我們可以做的雖然好:

template <typename T> 
class output_argument 
{ 
public: 
    template <typename U> 
    friend output_argument<U> out(U& ref); 

    T& get() const 
    { 
     return mRef; 
    } 

    operator T&() const 
    { 
     return get(); 
    } 

private: 
    explicit output_argument(T& ref) : 
    mRef(ref) 
    {} 

    output_argument& operator=(const output_argument&); // not defined 

    T& mRef; 
}; 

template <typename U> 
output_argument<U> out(U& ref) 
{ 
    return output_argument<U>(ref); 
} 

,並提供:

void foo(int x, output_argument<float> f) 
{ 
    int i = static_cast<int>(f); 

    f.get() = static_cast<float>(i + x); 
} 

int main() 
{ 
    float f = 5.0f; 

    //fails: foo(1, f); 
    foo(1, out(f)); 
} 

但通常這類工具是沒有必要的,因爲函數的名字應該傳達發生了什麼論據:swap(x, y)相當明確修改論據!返回值應該用返回類型來完成,進一步限制了這個工具可以使用的情況。

+0

此外,使用移動語義時,您在返回值時沒有爲副本支付性能損失。因此,使用out-parameter的典型模式應該很少。 –