2016-09-10 69 views
-1

我一直在關注這個tutorial,我無法理解這一部分。CPP常量函數參數說明

所以說,按值傳遞創建數據的副本,以便可以ineffiecient,因爲它產生的數據副本,是有道理的:

string concatenate (string a, string b) 
{ 
    return a+b; 
} 

那麼你有這個,要「解決創建數據副本「問題:

string concatenate (string& a, string& b) 
{ 
    return a+b; 
} 

這是有道理的,因爲它使用引用。

但我不明白這一點:

string concatenate (const string& a, const string& b) 
{ 
    return a+b; 
} 

它說:

通過合格他們爲const,功能禁止修改A和B都不值,但實際上可以以引用(參數的別名)的形式訪問它們的值,而不必製作字符串的實際副本。

爲什麼不使用第二種方式?在這個例子中,無論如何都不會修改數據?有人能給我一個更好的例子嗎?

僅僅是出於安全原因嗎?

+0

嘗試'concatenate(string(「Hello」),string(「world」));'用第二個版本。 – DeiDei

+0

@DeiDei的例子是一個很好的答案。除了保證不修改外,它允許傳遞臨時值。 –

回答

1

爲什麼不使用第二種方式?在這個例子中,無論如何都不會修改數據?有人能給我一個更好的例子嗎?

在你的情況下,在你寫函數的地方,這真的沒有關係,因爲你自己並沒有改變參數。

一個更好的例子

用於使用超過const引用的引用一個更好的例子是例如具有交換功能。以此爲例,其中交換2個整數。

void swap(int& a, int& b) 
{ 
    int temp = a; 
    a = b; 
    b = temp; 
} 

現在,在上面的例子中,你不能使用const參考,因爲分配給ab將有資格作爲修飾。在上面的函數中,引用非常有用,const替代方法不起作用。

一個不太具體例

這裏是一個不太具體的例子,示出相同的概念作爲swap(a,b)功能:

void pre_incr(int& a) 
{ 
    ++a; 
} 

現在爲什麼這個函數比swap()少混凝土的原因一個是,你可以平等使用這樣的價值:

void pre_incr(int a) 
{ 
    return ++a; 
} 

無論哪種方式,兩種功能都說明了通過const參考和通過正常參考之間的差異,並且還傳遞了值。

+0

但在我的問題中,使用「const」會帶來怎樣的性能提升?無論如何,副本並沒有被創建,就像你說的沒有改變。當我只使用引用不是表現相同? (在我的例子中) –

+0

編譯器可以優化並且不允許修改參數,這會讓編譯器拋出一個錯誤,比如說,如果'a'或'b',你修改了字符串。 –

-1

當你在沒有const的第一個方法中傳遞一個字符串,並且沒有&時,它需要被複制到效率低下的函數中。當你傳遞一個引用時,它不會被複制。當你通過const引用傳遞時,它避免了複製的低效率,而不允許函數修改字符串。

2

如果字符串你確實有是常量,或者你只需​​要他們常量引用,那麼你可以將它們傳遞給這個函數:

string concatenate (const string& a, const string& b); 

但你不能把它們傳遞給這個函數:

string concatenate (string& a, string& b); 

如果您的字符串不是常量,那麼您可以將它們傳遞給任一函數。因此,除了確保不會無意修改字符串,參數const允許使用更多功能,可以接受const或非const參數。

例如:

string concatenate_non_const (string& a, string& b) 
{ 
    return a+b; 
} 

string concatenate_const (const string& a, const string& b) 
{ 
    return a+b; 
} 

int main() 
{ 
    std::string s1 = "hello"; 
    std::string s2 = "world"; 
    const std::string cs1 = "hello"; 
    const std::string cs2 = "world"; 

    concatenate_const(s1, s2);  // okay 
    concatenate_const(cs1, cs2);  // okay 

    concatenate_non_const(s1, s2); // okay 
    concatenate_non_const(cs1, cs2); // error 
} 

此外,除了其聲明爲const對象,也有臨時變量來思考,不能綁定到非const引用。

concatenate_const("hello", "world");  // okay 
concatenate_non_const("hello", "world"); // error 
0

難道僅僅是做了安全的原因是什麼?

構成編程語言的大部分內容都是「安全原因」,否則我們可能會像代碼一樣在組件中跳過標籤。

製作一個常量字符串的函數引用的參數有兩個目的:

  • 你可以不小心修改引用字符串。
  • 它清楚地記錄了「你通過的字符串將而不是被修改」爲其他程序(或你未來的自己)和編譯器(和優化器)。

考慮這種情況:

string a = "foo", b = "bar"; 
cout << concatenate(a, b); // "foobar" 

你得到你所期望的,即使你修改傳遞的字符串中的級聯功能

string a = "foo", b = "bar"; 
cout << concatenate(a, b); 
// some code 
string c = "baz"; 
cout << concatenate(a, c); // "Aaaabaz" 

即使考慮尋找到concatenate之前,你可能會搜索所有的,「一些代碼」,找到修改a ...

還要注意,第一個例子(單次使用的參數字符串)是你在單元測試中可能找到的concatenate