[英]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);
}
};
我注意到如果執行此操作:
std::set<uint32_t> returned = test.GetValues ();
returned
的變量得到一個副本 ,而不是引用,為什么?
const std::set<uint32_t> & GetValues () const
函數是否必須包含雙const
(返回值上的一個和函數名稱后的一個)?
編輯:其他問題:
知道std::set<uint32_t> returned = test.GetValues ();
創建一個副本。 如果我這樣做:
test.GetValues ().size ();
為了調用size ()
函數(或返回的對象的任何其他成員),是臨時創建副本還是使用返回的引用解析所有副本?
具有三個函數(按值返回,按常量引用和按引用)是否不好?
// 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_values
的const
引用。
因此,如果包含第二個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.