簡體   English   中英

按值或按引用傳遞構造函數參數

[英]Passing constructor arguments by value or by reference

只是一個關於這樣的函數的快速問題:

class Test {
  public:
    Test(vector<int>& v) {
      v_ = v;
    }
  private:
    std::vector<int> v_;
};

使用Test(vector<int>& v)Test(vector<int> v)之間有什么區別? 我似乎知道第一個應該更快,因為它是傳遞參考。 但我不確定是否存在其他差異。

不同之處在於使用Test(vector<int>& v) (其中BTW是左值引用)v指的是原始對象,而使用Test(vector<int> v)則有副本。 下面的示例代碼演示了int和普通函數的區別(請注意,對於int ,pass-by-value實際上更快!):

#include <iostream>

int global_i;

void pass_by_value(int i)
{
  std::cout << "pass by value:\n";
  std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
  i++;
  std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
  global_i++;
  std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}

void pass_by_reference(int& i)
{
  std::cout << "pass by reference:\n";
  std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
  i++;
  std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
  global_i++;
  std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}

void pass_by_const_reference(int const& i)
{
  std::cout << "pass by const reference:\n";
  std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
  // i++; not allowed!
  // std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
  global_i++;
  std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}

int main()
{
  global_i = 1;
  pass_by_value(global_i);

  global_i = 1;
  pass_by_reference(global_i);

  global_i = 1;
  pass_by_const_reference(global_i);
}

這個輸出是:

pass by value:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 1
after global_i++: i = 2, global_i = 2
pass by reference:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 2
after global_i++: i = 3, global_i = 3
pass by const reference:
initially: i = 1, global_i = 1
after global_i++: i = 2, global_i = 2

如您所見,通過按值調用,參數和傳遞的變量是完全獨立的。 遞增參數不會更改傳遞的變量,並且遞增傳遞的變量不會更改參數。 另一方面,通過引用傳遞,參數只允許訪問傳遞的變量:無論你增加哪一個都無關緊要,因為它們是相同的。 通過const引用傳遞,它們也是相同的,但是你不允許使用這個參數(盡管有這種方法)。 但是,該參數仍然反映了對傳遞的變量的任何更改。

這些是功能上的差異。 但是有一些差異:對於傳遞值和傳遞const引用,您可以使用rvalue,如call_by_value(2)call_by_const_reference(2) 對於按值調用,很明顯會發生什么:參數得到值2,就是這樣。 但是對於const引用,有一個期望的對象(例如,你可以在函數中獲取該對象的地址)。 因此,在這種情況下,創建臨時對象。 對於非const引用的調用,您不能傳遞右值。

C ++ 11在混合中添加了另一種類型,即右值引用。 這些用&&代替&表示。 在函數內部,它們的行為與普通(左值)引用完全相同,但它們的區別在於它們可以綁定到右值,即使它們不是常量。 此外,如果您將它們用作返回類型,則調用表達式將為rvalue類型,就像您返回了一個值一樣。 特別是,您將無法傳遞函數的結果,該函數將rvalue引用返回到期望左值引用的函數,就像您不能使用文字2那樣。

您的代碼中沒有右值引用,只需要進行大量不必要的復制。

但是,既然我們正在談論這個話題,那么這是用移動語義編寫它的正確方法:

Test(std::vector<int> v)  // by value!
:  v_(std::move(v))
{
}

在11之前的世界中,下一個最好的方法是通過const-reference獲取參數並復制它:

Test(std::vector<int> const & v)
:  v_(v)
{
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM