关于使用返回的引用

About using returned references

本文关键字:引用 返回 于使用      更新时间:2023-10-16

我在试图理解c++中返回引用的正确用法时遇到了一些麻烦。我有一个类,里面有一个"大"对象。我希望能够通过返回const引用来在类"只读"模式之外使用该对象。

问题是我不太明白对象何时被复制,何时不被复制。

大多数关于返回引用的问题都是关于返回对象在堆栈上分配的,这不是我特别关心的问题,所以我准备了这个小例子:

class foo {
  int a;
public:
  foo() {
    a = 3;
  }
  int& getInt() {
    return a;
  }
  const int& useInt() {
    return a;
  }
  void print() {
    cout << "Inside class: a = " << a << endl;
  }
};
int main() {
  foo foo1;
  int& goodRef = foo1.getInt();
  int badRef = foo1.getInt();
  goodRef = 4;
  badRef = 5;
  foo1.print();
  foo1.getInt() = 6;
  foo1.print();
  int usingIt = 10*foo1.useInt();
}

我理解的是:

  • int& goodRef = foo1.getInt();中没有复制任何东西,只有类拥有a存在。
  • int badRef = foo1.getInt();中,badRef是a的副本,因此有2个单独的对象,abadRef

因此,根据捕获返回值的对象类型,它被复制或不复制,所以我的问题是:

当我在int usingIt = 10*foo1.useInt();中使用引用时,它是复制的,然后用于乘法还是仅使用类内的值?

在本例中,这并不重要,因为它只是一个int型,但如果它是一个大对象,这将是一个大问题。

谢谢!

编辑:感谢所有的答案,但我知道在类中有这样的方法是不好的,我只是为了这个例子而把它们放在这里。

我实际的类里面有一堆对象和一个接口等等,但是有一个特定的对象是glm::mat4。我想要的是能够写出像glm::vec4 finalVec = foo1.getMatrix() * vec这样的东西。但是我不希望整个矩阵被复制然后相乘,而是我想使用已经在我的类中的矩阵来执行乘法,同时不让用户修改它。我认为类似的useInt,但与mat4将工作,但我不确定,这就是为什么我问这个问题。

glm规范对我来说非常困惑,但我认为操作符*被描述为:

glm::mat4 operator* (glm::mat4 const & m, glm::vec4 const & v);

在您的示例int usingIt = 10*foo1.useInt();中,operator*(),取决于它的参数签名和内部,可能会导致您的对象的副本发生,此时它将被赋值(而不是再次复制)到usingIt的值。如果您的对象是聚合对象类型或类对象类型,则使用对象类型的赋值操作符的副本通常会使用编译器优化步骤省略。

一般来说,无论何时将l值引用类型(即T&const T&)复制到聚合对象或将类对象复制到非引用类型(即T类型),都要在返回的对象引用上调用复制构造函数、构造函数、赋值操作符或转换操作符。

如果getInt返回int&,为什么要在int中捕获返回值?你期望什么,编译器改变你的源代码使用int的引用?它只能复制引用所指向的对象的值。

另一方面,我认为你有一个不好的例子。要么定义一个返回const引用的方法:
int const & getInt() { return a; }

或者提供两个方法,一个是const方法,一个是非const方法:

int& getInt() { return a; }
int const & getInt() const { return a; }

同时拥有getIntuseInt并不会阻止任何人使用getInt,并以一种不希望的方式改变对象的值。

当你使用const引用时,你只能使用这个对象的const方法。例如,当你有STL vector时,你可以获取size,但你不能将元素push_back给它。

vector<int> a;
vector<int> &c = a;
const vector<int> &b = a;
a.size();
b.size();
a.push_back(4);
c.push_back(4);
//our vector is now 4 4
//b.push_back(4); compilation error

在c++中,当你想复制时,你可以复制:例如
函数,复制:int x(vector<int> b)
不复制的函数:int x(vector<int> &b)
你可以在这里阅读更多