简体   繁体   English

返回对恒定大小的指针数组的引用的最佳方法是什么?

[英]What is the best way to return reference to a constant sized array of pointers?

I have an array of pointers declared as a class member like this: 我有一个声明为类成员的指针数组,如下所示:

class Bar
{
private:
  static constexpr int SIZE = 10;    
  Foo* m[SIZE];
}

In one of my class methods, I would like to return a pointer (or preferably, a reference) to this array. 在我的一种类方法中,我想返回一个指向此数组的指针(最好是一个引用)。 The array has a known size at compile time, but I am keeping track of how many items I have put in there (it is a buffer of stuff). 该数组在编译时具有已知的大小,但是我一直在跟踪我在其中放置了多少个项目(它是东西的缓冲区)。

What is the best way to return a reference to this array in C++11 ? 在C ++ 11中返回对此数组的引用的最佳方法是什么?

Here are the things I have tried: 这是我尝试过的事情:

GetArray(Foo* &f[], unsigned &size) const

I like the syntax because it makes it clear that the reference value is an array of pointers, but this gives a compiler error: Declared as array of references of type Foo* 我喜欢语法,因为它可以清楚地表明引用值是一个指针数组,但这会产生编译器错误: Declared as array of references of type Foo*

GetArray(Foo** &f, unsigned &size) const
{
  f = m;
  size = mSize;
}

Gives me: Error: assigning to Foo **' from incompatible type Foo *const[10] . 给我:错误: Foo **' from incompatible type Foo *const[10]分配给Foo **' from incompatible type Foo *const[10] Casting mFoo to (Foo**) alleviates the error, but IMHO, this is not elegant. mFoo(Foo**)减轻错误,但是恕我直言,这不是很优雅。

I would seek to use a std::array or a std::vector in most cases. 在大多数情况下,我会尝试使用std::arraystd::vector If you are determined to use a raw array then you could go this way with it: 如果确定要使用原始数组,则可以通过以下方式进行处理:

typedef int Foo;

typedef Foo* (&FooPtrArrayRef)[10]; // to make the syntax less hairy

class Bar
{
private:
  Foo* m[10];

public:
  // First way without using typedef
  Foo* (&getArray())[10]
  {
      return m;
  }

  // Nicer looking way with a typedef
  FooPtrArrayRef getArrayByRef()
  {
      return m;
  }
};

int main()
{

    Bar b;

    Foo* (&array)[10] = b.getArray();

    std::cout << (sizeof(array) / sizeof(Foo*)) << '\n';

    // Alternative using "size deduction"

    Foo* (&array2)[sizeof(b.getArray()) / sizeof(Foo*)] = b.getArray();

    std::cout << (sizeof(array2) / sizeof(Foo*)) << '\n';

    // MUCH nicer using the typedef

    FooPtrArrayRef array3 = b.getArrayByRef();

    std::cout << (sizeof(array3) / sizeof(Foo*)) << '\n';
}

The syntax is pretty obscure though. 语法虽然很晦涩。

The benefits of this is approach is that it retains the full type information of the array you are passing by reference. 这种方法的好处是它保留了您通过引用传递的数组的完整类型信息。 The obscure syntax is necessary to avoid the type collapsing to a Foo** . 晦涩的语法对于避免类型崩溃为Foo**是必需的。 By retaining the full type of the array you retain the ability to know its size at compile time using the sizeof() operator. 通过保留数组的完整类型,您可以保留使用sizeof()运算符在编译时知道其大小的能力。

Nobody posted an answer using std::array yet, it is a very simple replacement: 尚无人使用std::array发布答案,这是一个非常简单的替代方法:

class Bar
{
    std::array<Foo *, 10>  m;
public:
    std::array<Foo *, 10> & getArray() { return m; }
    std::array<Foo *, 10> const & getArray() const { return m; }
};

This seems to me a lot simpler than the hoops you have to jump through to use your C-style array version. 在我看来,这比使用C样式数组版本所必须克服的困难要简单得多。

To avoid code duplication you could typedef std::array<Foo *, 10> FooArray; 为了避免代码重复,您可以typedef std::array<Foo *, 10> FooArray; .

The technique of having both a const and a non- const implementation is a common pattern for accessor functions which return a reference or a pointer. 同时具有const和非const实现的技术是访问器函数的一种常见模式,该访问器函数返回引用或指针。 (It's not required if your accessor returns by value, of course). (当然,如果您的访问器按值返回,则不需要这样做)。

here's another approach that returns the array reference and the current size as a tuple: 这是将数组引用和当前大小作为元组返回的另一种方法:

#include <tuple>
#include <functional>
#include <algorithm>
#include <iterator>
#include <iostream>

struct Foo {};

using FooBuffer = Foo*[10];

class Bar
{
public:
  Bar() 
  : _m { nullptr }
  {
      _m[0] = new Foo;
      _m[1] = new Foo;
      _items = 2;
  }

  ~Bar() {
      for(auto fp : _m)
        delete fp;
  }

  std::tuple<FooBuffer&, size_t> getInfo() {
      return std::make_tuple(std::ref(_m), _items);
  }
private:    
  Foo* _m[10];
  size_t _items;
};


int main() {
    Bar b;

    auto info = b.getInfo();
    FooBuffer& buf = std::get<0>(info);
    size_t items = std::get<1>(info);

    for(Foo** p = buf ; p != buf + items ; ++p) {
        std::cout << "Foo at " << std::hex << *p << std::endl;
    }

return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM