返回对类成员容器的元素的引用

Returning a reference to an element of a class member container

本文关键字:元素 引用 成员 返回      更新时间:2023-10-16

Foo的行为类似于循环迭代器。 尽管我对此感到紧张,但下面的代码编译良好,但会产生运行时错误。 即使我从 get_current() 中删除常量,我也会收到错误。 当然,我可以返回一个指针,它会起作用;但是,返回引用后会获得更好的安全性吗?

#include <iostream>
#include <array>
#include <memory>
class Foo
{
public:
  Foo();
  void next();
  const int& get_current() const;
private:
  std::array<std::unique_ptr<int>, 3> arr_;
  unsigned i_;
};
Foo::Foo() : i_(0)
{
  arr_[0] = std::unique_ptr<int>(new int(5));
  arr_[1] = std::unique_ptr<int>(new int(6));
  arr_[2] = std::unique_ptr<int>(new int(7));
}
void Foo::next()
{
  ++i_;
  i_ %= 3;
}
const int& Foo::get_current() const 
{
  return *arr_[i_];
}
int main()
{
  Foo foo;
  int* p;
  *p = foo.get_current();
  //do something with p
  std::cout << *p << std::endl;
  foo.next();
  *p = foo.get_current();
  //do something with p
  std::cout << *p << std::endl;
  return 0;
}
int* p;

这是一个未初始化的指针,不指向任何内容。取消引用它会给出未定义的行为。

*p = foo.get_current();

这将取消引用无效指针。繁荣!

也许您希望它指向数组元素

p = &foo.get_current();

或者,您可能想要数组元素的副本

int n;
n = foo.get_current();

foo.get_current();很可能返回一个const引用,但之后你在分配给*p时尝试获取它的值副本。

分配给*p是导致您麻烦的原因,因为p未初始化。这是未定义的行为,在您的情况下表现为运行时错误。

您可以使用const int& p = foo.get_current();这样的代码,但请注意,一个引用只能绑定一次,因此您必须小心范围。

或者,您可以使用std::shared_ptr<int>并将其作为get_current()的返回类型,并完全去除代码中的裸指针。

*p = ... 您在没有正确初始化的情况下取消引用int* P

将 main 中的代码更改为

 int p; // Remove *
 p = foo.get_current();
 //do something with p
 std::cout << p << std::endl;

或者如果你真的想使用指针

 const int* p;
 p = &foo.get_current();
  // ^ Take the address