从c++方法返回引用和副本
Returning a reference vs. a copy from a C++ method
我目前正在学习c++,我对从方法返回引用的概念有点困惑。考虑下面的玩具示例:
#include <iostream>
#include <vector>
class IntHolder {
private:
std::vector<int> d_values;
public:
IntHolder() {
d_values.push_back(1);
d_values.push_back(2);
d_values.push_back(3);
}
std::vector<int> &values() {
return d_values;
}
};
int main(int argc, char **argv) {
IntHolder h;
std::vector<int> ret_val = h.values();
std::cout << ret_val.size() << std::endl;
ret_val.push_back(4);
ret_val.push_back(5);
std::cout << h.values().size() << std::endl;
return 0;
}
将以下内容打印到标准输出:
3
3
既然我们返回的是对d_values
的引用,那么返回的对象不应该与存储在IntHolder
实例中的对象相同吗?因此,当再次调用h.values()
时,我们应该看到大小为5?
既然不是这样,那么返回对象的引用和对象的副本有什么区别呢?当你从一个方法返回时有什么不同吗?
您从values
函数返回引用,但您没有将返回的对象分配给引用变量。相反,您正在对它进行复制,因为您将其分配给名为ret_val
的新std::vector<int>
。
您希望像这样修改代码,以便捕获返回的引用:
std::vector<int>& ret_val = h.values();
或者简单地:
auto& ret_val = h.values();
您的方法返回一个引用,但是您随后将结果赋值给另一个向量,从而导致复制。要解决这个问题,将ret_val
定义更改为:
std::vector<int> & ret_val = h.values();
如果返回引用,则返回相同的对象,而不是创建副本。从根本上看,它似乎正如你所期望的那样:
std::cout << h.values().size() << std::endl;
h.values().push_back(4);
h.values().push_back(5);
std::cout << h.values().size() << std::endl;
回来3
5
是另一个错误。让我们看看
std::vector<int> ret_val = h.values();
您发现ret_val
是h.d_values
的副本,而h.values()
返回对它的引用。我们可以将上面的代码重写如下:
std::vector<int> &ret_ref = h.values(); // object returned by `h.values()`
std::vector<int> ret_val = ret_ref;
如果你调用ret_ref.push_back(4)
, h.d_values
将改变。但是ret_val
是返回对象的副本,不会影响h.d_values
。
相关文章:
- 使用unique_ptr并返回引用,或者我应该使用shared_ptr并在需要时制作副本
- C ++引用函数参数似乎包含原始对象的副本,而不是充当"real reference"
- 为什么基于范围的 for 循环中的结构化绑定只是一个副本而不是引用?
- 标准库容器结构是否存储副本或引用?
- 如何声明接受转发引用并返回引用或副本的函数模板
- 如何在我的源代码中找到所有发生的情况,其中std :: string被传递给方法作为副本而不是恒定引用
- 取消引用指针以创建数组的副本
- 返回不带副本 ctor 的引用
- 为什么在C 11中推荐的值(如果需要副本),如果const引用也只花费单个副本,则建议通过值(如果需要副本)
- 如何通过制作副本从函数返回引用
- 可以在同一函数中引用副本本地变量是否可以
- 为什么从三元文字中绑定到const引用副本
- 传递常量引用与创建临时常量副本相同,那么为什么要传递常量引用
- 为什么在 constexpr 函数中允许返回对常量指针的引用,但不返回副本
- 初始化引用时何时以及为何获得副本
- 处理对“vector_binary_operation”类中“表达式”的引用,而无需不必要的副本
- 按方法返回副本或引用
- 您能否从抽象引用创建具体对象的副本
- 常量引用和创建副本
- C++通过对构造函数的引用传递.成员将是一个完整的私人副本