简体   繁体   English

构造范围内的向量而不复制

[英]construct a vector in range without copying

I have a class that wraps a big array of bytes that are network packets. 我有一个包含大量字节的类,这些字节是网络数据包。 The class implements a queue and provides (among others) front() function that returns a const vector of bytes that constitute the oldest packet in the queue. 该类实现一个队列并提供(以及其他) front()函数,该函数返回构成队列中最旧数据包的字节的const向量。

class Buffer{
  unsigned char data[65536];
  unsigned int offset;
  unsigned int length;
  [...]//other fields for maintaining write ptr etc.

public:
  const std::vector<unsigned char> front(){
    return std::vector<unsigned char>(data + offset, data + offset + length);
  }

  //other methods for accessing the queue like
  //pop(), push(), clean() and so forth...
  [...]
}

The performance of above implementation of front() function suffers from unnecessary copying bytes from the range occupied by the current packet. 上述front()函数实现的性能受到当前数据包占用范围内不必要的复制字节的影响。 Since the vector is const, there is no need of making a copy of the data. 由于向量是常量,因此不需要复制数据。 What I want is to create a vector on the data that are already stored in the buffer. 我想要的是在已经存储在缓冲区中的数据上创建一个向量。 Of course destructor of the vector should not deallocate the memory. 当然,向量的析构函数不应该释放内存。

You have some options available to you: 您有一些选择:

  1. Rather than returning a vector , just return a const char* : 而不是返回一个vector ,只需返回一个const char*
const char* front() {
    return data;
}
  1. Consider using a standard container, such as a string data as your Buffer member. 考虑使用标准容器,例如string data作为Buffer成员。 This will allow you to do: 这将允许您:
const string& front() {
    return data;
}
  1. The best option though is if you have C++17 or access to experimental::string_view you could just do: 但最好的选择是,如果您有C ++ 17或访问experimental::string_view您可以这样做:
const string_view front() {
    return string_view(data);
}

Just a convention comment, there is going to be an expectation of front that it will behave like other standard containers, which: 只是一个约定评论, front会有一个期望,它将像其他标准容器一样,其中:

Returns a reference to the first element in the container. 返回对容器中第一个元素的引用。
Calling front on an empty container is undefined. 在空容器上调用前端是未定义的。

[ source ] [ 来源 ]

Bringing front to apply to bare on fixed size arrays was also discussed by the C++ standards committee: front and back Proposal for iterators Library C ++标准委员会还讨论了在固定大小的阵列上应用裸露的前端正面和背面的迭代器库建议

As it is this method more closely resembles data , which: 因为这种方法更接近data ,其中:

Returns a pointer to the block of memory containing the elements of the container. 返回指向包含容器元素的内存块的指针。

[ source ] [ 来源 ]

If you're looking to avoid unnecessary copying then you'll need to return a view into the data. 如果您希望避免不必要的复制,那么您需要将视图返回到数据中。 You can either provide a front_begin() and front_end() set of functions: 您可以提供front_begin()front_end()函数集:

const char *front_begin() const
{
  return data + offset;
}

const char *front_end() const
{
  return data + offset + length;
}

Or write a wrapper class: 或者写一个包装类:

class Data
{
private:
  const char *m_Begin;
  const char *m_End;

public:
  Data(const char *begin, const char *end) : m_Begin(begin), m_End(end)
  {
  }

  const char *begin() const
  {
    return m_Begin;
  }

  const char *end() const
  {
    return m_End;
  }
}

And have your front() method return one of these: 并让你的front()方法返回其中一个:

Data front()
{
  return Data(data + offset, data + offset + length)
}

If you're using C++11 then you can use a Data instance in a ranged based for loop: 如果您正在使用C ++ 11,那么您可以在基于范围的for循环中使用Data实例:

Data data = buffer.front();
for(char c : data)
{
  // Do something with the data
}

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

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