C++ return by reference 和 return by const-reference 值被复制
C++ return by reference and return by const-reference value is copied
我对返回 class 成员变量的引用有一些疑问。
我有以下代码:
#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
(return值和函数名后一个) ?
编辑:其他问题:
知道std::set<uint32_t> returned = test.GetValues ();
创建一个副本。如果我这样做:
test.GetValues ().size ();
为了调用 size ()
函数(或 returned 对象的任何其他成员),是临时创建的副本还是全部使用 returned 引用解析?
三个函数不好吗,return按值,按常量引用,按引用?
// 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;
}
The variable returned gets a copy, not a reference, why?
当您使用引用来初始化一个类型不是引用的值时,您会得到一个副本,例如
#include <cassert>
int main() {
int a = 1;
const int& a_ref = a;
int b = a_ref;
assert(&b != &a);
}
Does the const std::set<uint32_t> & GetValues () const
function must contain the double const
第二个const是作为成员函数限定符来应用的,意思是当你的class的调用实例是const限定时可以调用该方法。例如
Test test;
test.GetValues(); // 1
const Test& test_ref = test;
test_ref.GetValues(); // 2
这里1
会调用非常量版本,2
会调用const
限定的方法
此外,const
限定方法不会让您 return 非常量引用它自己的值,因此您必须 return 对您的成员的 const
引用变量 m_values
。
因此,如果您包含第二个 const
,那么您必须包含第一个 const
,但是如果您只是将 return 类型设为 const
引用,那么您不需要制作方法 const
。例如
const std::set<uint32_t>& GetValues() // 1
std::set<uint32_t>& GetValues() { return m_values; } // 2
此处允许1
但不允许2
。
如果您好奇的话,发生这种情况的原因是因为隐式 this
指针 const
有资格成为 const
限定方法中指向 const
的指针。
In order to call the size () function (or any other member of the returned object), is a copy created temporarily or all is resolved with the returned reference?
将在引用上调用 size()
方法!测试此类事物的最佳方法是在快速测试用例中进行尝试 https://wandbox.org/permlink/KGSOXDkQESc8ENPW(请注意,我已经使测试比演示所需的复杂一点)
Is it bad to have three functions, return by value, by const-reference and by reference?
如果您将用户暴露给可变引用,那么让他们制作副本(这就是为什么您使用按值)方法的最佳方法是让他们通过初始化一个非-ref 使用 returned 引用限定 set
(就像您最初所做的那样)
此外,在您的代码中,以下两种方法之间存在歧义
std::set<uint32_t> GetValues() const
const std::set<uint32_t>& GetValues () const
因为唯一不同的是 return 类型,and you cannot overload a function off the return type。
变量returned
是一个单独的对象,必须有自己的值。
因此在这个声明中
std::set<uint32_t> returned = test.GetValues ();
函数返回的引用所引用的值被复制到对象中returned
。
如果您声明引用而不是对象,例如
std::set<uint32_t> &returned = test.GetValues ();
那么在这种情况下,引用 returned
将引用 class 对象的原始对象,并由函数返回的引用进行初始化。
第二个问题返回类型不参与函数重载解析
例如,如果您要删除第二个 const 限定符
const std::set<uint32_t> & GetValues ();
std::set<uint32_t> & GetValues ();
那么对于这样的调用,这两个函数之间存在歧义
std::set<uint32_t> returned = test.GetValues ();
我对返回 class 成员变量的引用有一些疑问。
我有以下代码:
#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
(return值和函数名后一个) ?
编辑:其他问题:
知道
std::set<uint32_t> returned = test.GetValues ();
创建一个副本。如果我这样做:test.GetValues ().size ();
为了调用
size ()
函数(或 returned 对象的任何其他成员),是临时创建的副本还是全部使用 returned 引用解析?三个函数不好吗,return按值,按常量引用,按引用?
// 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; }
The variable returned gets a copy, not a reference, why?
当您使用引用来初始化一个类型不是引用的值时,您会得到一个副本,例如
#include <cassert>
int main() {
int a = 1;
const int& a_ref = a;
int b = a_ref;
assert(&b != &a);
}
Does the
const std::set<uint32_t> & GetValues () const
function must contain the double const
第二个const是作为成员函数限定符来应用的,意思是当你的class的调用实例是const限定时可以调用该方法。例如
Test test;
test.GetValues(); // 1
const Test& test_ref = test;
test_ref.GetValues(); // 2
这里1
会调用非常量版本,2
会调用const
此外,const
限定方法不会让您 return 非常量引用它自己的值,因此您必须 return 对您的成员的 const
引用变量 m_values
。
因此,如果您包含第二个 const
,那么您必须包含第一个 const
,但是如果您只是将 return 类型设为 const
引用,那么您不需要制作方法 const
。例如
const std::set<uint32_t>& GetValues() // 1
std::set<uint32_t>& GetValues() { return m_values; } // 2
此处允许1
但不允许2
。
如果您好奇的话,发生这种情况的原因是因为隐式 this
指针 const
有资格成为 const
限定方法中指向 const
的指针。
In order to call the size () function (or any other member of the returned object), is a copy created temporarily or all is resolved with the returned reference?
将在引用上调用 size()
方法!测试此类事物的最佳方法是在快速测试用例中进行尝试 https://wandbox.org/permlink/KGSOXDkQESc8ENPW(请注意,我已经使测试比演示所需的复杂一点)
Is it bad to have three functions, return by value, by const-reference and by reference?
如果您将用户暴露给可变引用,那么让他们制作副本(这就是为什么您使用按值)方法的最佳方法是让他们通过初始化一个非-ref 使用 returned 引用限定 set
(就像您最初所做的那样)
此外,在您的代码中,以下两种方法之间存在歧义
std::set<uint32_t> GetValues() const
const std::set<uint32_t>& GetValues () const
因为唯一不同的是 return 类型,and you cannot overload a function off the return type。
变量returned
是一个单独的对象,必须有自己的值。
因此在这个声明中
std::set<uint32_t> returned = test.GetValues ();
函数返回的引用所引用的值被复制到对象中returned
。
如果您声明引用而不是对象,例如
std::set<uint32_t> &returned = test.GetValues ();
那么在这种情况下,引用 returned
将引用 class 对象的原始对象,并由函数返回的引用进行初始化。
第二个问题返回类型不参与函数重载解析
例如,如果您要删除第二个 const 限定符
const std::set<uint32_t> & GetValues ();
std::set<uint32_t> & GetValues ();
那么对于这样的调用,这两个函数之间存在歧义
std::set<uint32_t> returned = test.GetValues ();