将向量成员变量返回到外部类的最佳方法

时间:2014-12-18 19:57:37

标签: c++ vector reference smart-pointers

我正在尝试用c ++写一个LED条带驱动程序。现在我有一个Strip类和一个Driver类; Strip类抽象出具有多个像素的LED条带,而Driver类将Strip类聚合到单个缓冲区中以通过UDP连接发送。

相关的部分类:

class Strip {
  public:
    ...
    ??? getPixelData();
    int getPixelDataLength();
  protected:
    std::vector<unsigned char> mPixelData;

class Driver {
  public:
    ...
    void aggregateStrips();
  protected:
    vector<unsigned char> mBuffer;

serialize将所有红绿蓝像素数据写入vector<unsigned char>。然后,驱动程序调用{​​{1}}将地址调到Strip.getPixelData(),然后mPixelData调出getPixelDataLength()的字节数。

memcpy()做了类似的事情:

aggregateStrips()

我的问题是 - int packetLength = 0; for(auto strip : Strips) { memcpy(&mBuffer[packetLength], strip->getPixelData(), strip->getPixelDataLength()); packetLength += strip.getPixelDataLength(); } 应该返回什么?它应该向向量返回一个智能指针(getPixelData()?)吗?或者也许是参考?我只想要地址(和长度),因为我打算shared_ptr它。

谢谢!

3 个答案:

答案 0 :(得分:7)

通常,您会返回对向量(std::vector<unsigned char> const &)的const引用,在这种情况下,您还应该使方法成为const,因为它不会修改对象:

std::vector<unsigned char> const & getPixelData() const;

来电者可以决定是否需要复制。

// Causes copy-initialization.
std::vector<unsigned char> copy = a_strip.getPixelData();

// Binds a new reference to the existing vector; no copy is made.
std::vector<unsigned char> const & not_a_copy = a_strip.getPixelData();

getPixelDataLength()也可能成为该类的const成员。尝试使任何不改变对象const成员的成员,因为它允许在const Strip对象上调用它们。

答案 1 :(得分:1)

std::vector通过其data()方法公开其管理的缓冲区,在这种情况下,该方法将返回unsigned char*const unsigned char *,具体取决于Strip / mBufferconst。这个方法是在C ++ 11中添加的。

作为旁注,将您的只读方法设置为const(在带括号的方法参数之后)是一个很好的设计,因此可以在类const实例上调用它们并且不允许修改任何成员变量。

我将getPixelData()定义为:

const unsigned char* getPixelData() const
{
  return mBuffer.data();
}

同样,我将getPixelDataLength()写为:

std::size_t getPixelDataLength() const
{
  return mBuffer.size();
}

另一方面,for(auto strip : Strips)实际上复制了每个条带。如果您引用每个现有条带而不复制它,您的程序将更有效:

for (const auto& strip : Strips) {
  // ...
}

答案 2 :(得分:1)

我不会返回向量,而是将一对(const)迭代器返回到向量的开头和结尾:

using PixelIterator = std::vector<unsigned char>::const_iterator;
class Strip {
 ... 
 PixelIterator begin() const {
   return mPixelData.begin();
 }
 PixelIterator end() const {
   return mPixelData.end();
 }
};

如果可以,我会避免在c ++中使用memcopy。使用迭代器,您可以轻松附加到缓冲区向量:

for(const auto& strip : strips)
  mBuffer.insert(mBuffer.end(). strip.begin(),  strip.end());

正如已经指出的那样,在基于范围的循环中使用auto&以避免复制。

您不需要维护单独的长度变量,因为您可以轻松获得std::vector的大小。