簡體   English   中英

C ++按引用返回和按常量引用返回值被復制

[英]C++ return by reference and return by const-reference value is copied

我有一些關於重新引用類成員變量的問題。

我有以下代碼:

#include <stdint.h>
#include <string>
#include <iostream>
#include <set>

void
PrintSet (const std::string & str, const std::set<uint32_t> & to_print)
{
  std::cout << str << " (" << to_print.size () << "): ";

  for (std::set<uint32_t>::const_iterator it = to_print.begin ();
          it != to_print.end (); ++it)
    {
      std::cout << *it << " ";
    }

  std::cout << "\n";
}

class Test
{
private:
  std::set<uint32_t> m_values;

public:

  Test () : m_values () { }

  void
  SetValues (const std::set<uint32_t> & values)
  {
    m_values = values;
  }

  const std::set<uint32_t> &
  GetValues () const
  {
    return m_values;
  }

  std::set<uint32_t> &
  GetValues ()
  {
    return m_values;
  }

  void
  Print () const
  {
    PrintSet ("TestInst", m_values);
  }
};
  1. 我注意到如果執行此操作:

     std::set<uint32_t> returned = test.GetValues (); 

    returned的變量得到一個副本 ,而不是引用,為什么?

  2. const std::set<uint32_t> & GetValues () const函數是否必須包含雙const (返回值上的一個和函數名稱后的一個)?

編輯:其他問題:

  1. 知道std::set<uint32_t> returned = test.GetValues (); 創建一個副本。 如果我這樣做:

     test.GetValues ().size (); 

    為了調用size ()函數(或返回的對象的任何其他成員),是臨時創建副本還是使用返回的引用解析所有副本?

  2. 具有三個函數(按值返回,按常量引用和按引用)是否不好?

     // Return by value std::set<uint32_t> GetValues () const { return m_values; } // Return by const-reference const std::set<uint32_t> & GetValues () const { return m_values; } // Return by reference std::set<uint32_t> & GetValues () { return m_values; } 

返回的變量得到一個副本,而不是引用,為什么?

例如,當您使用引用來初始化其類型不是引用的值時,將得到一個副本。

#include <cassert>

int main() {
    int a = 1;
    const int& a_ref = a;
    int b = a_ref;
    assert(&b != &a);
}

const std::set<uint32_t> & GetValues () const函數是否必須包含雙精度const

第二個const用作成員函數限定符,這意味着當您的類的調用實例是const限定的時,可以調用該方法。 例如

Test test;
test.GetValues(); // 1
const Test& test_ref = test;
test_ref.GetValues(); // 2

這里1將調用非const版本,而2將調用使用const限定的方法

此外, const限定方法將不允許您返回對其自身值的非const引用,因此您必須返回對成員變量m_valuesconst引用。

因此,如果包含第二個const則必須包含第一個const ,但是,如果僅將返回類型設為const引用,則無需將方法設為const 例如

const std::set<uint32_t>& GetValues() // 1
std::set<uint32_t>& GetValues() { return m_values; } // 2

這里允許1 ,但不允許2

如果您感到好奇,就會發生這種情況,是因為隱式this指針是const限定的,是const限定方法中指向const的指針。


為了調用size()函數(或返回的對象的任何其他成員),是臨時創建副本還是使用返回的引用解析所有副本?

size()方法將在引用上調用! 最好的測試方法是在一個快速的測試用例中進行嘗試https://wandbox.org/permlink/KGSOXDkQESc8ENPW (請注意,我使測試比演示所需的要復雜一些)

具有三個函數(按值返回,按常量引用和按引用)是否不好?

如果您的用戶暴露於可變引用,然后讓他們做一個副本(這就是為什么你有按值)的方法是讓他們通過初始化非裁判資格進行復制自己的最佳方式set與返回的參考(就像您最初所做的那樣)

同樣在您的代碼中,以下兩種方法之間也存在歧義

std::set<uint32_t> GetValues() const
const std::set<uint32_t>& GetValues () const

因為所有不同的是返回類型, 並且您不能在返回類型上重載函數

returned的變量是一個單獨的對象,必須具有自己的值。

因此,在此聲明中

std::set<uint32_t> returned = test.GetValues ();

將函數返回的引用所引用的值復制到returned的對象中。

例如,如果聲明一個引用而不是對象

std::set<uint32_t> &returned = test.GetValues ();

那么在這種情況下, returned的引用將引用類對象的原始對象,並由函數返回的引用進行初始化。

至於第二個問題,則返回的類型不參與重載的函數解析。

例如,如果您要刪除第二個const限定詞

const std::set<uint32_t> & GetValues ();
std::set<uint32_t> & GetValues (); 

那么這兩個函數之間就存在這樣的歧義

std::set<uint32_t> returned = test.GetValues ();

暫無
暫無

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

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