【问题标题】:How to create a vector around a buffer?如何在缓冲区周围创建一个向量?
【发布时间】:2018-05-27 07:16:12
【问题描述】:

我有一个类似于以下的代码:

 myLibFunc(std::vector<char > &data)
 {
     // dosomthing with data
 }
 myFunc(char *buffer,int bufferSize)
 {
       std::vector<char > mydata(buffer,buffer+bufferSize);
       myLibFunc(mydata);
 }

代码有效,但向量为自己分配内存,而不是使用已经可用的内存。

如何更改代码以使向量使用已经可用的内存而不分配额外的内存?

请注意,我不能更改函数的签名。

更新

我有两个功能:
在其中一个中,我收到一个缓冲区,我需要操作内存并将其作为向量传递给下一个函数。我试图实现的功能是接口的一部分,所以我无法更改它。另一个函数是我需要调用的库,所以我不能更改函数的签名。
问题是上面的代码分配了新的内存并将数据从缓冲区复制到它不是最优的。

【问题讨论】:

  • 首先,您创建一个 C 风格的 字符串 向量,而不是字符向量。至于您的问题,您似乎想要一个std::string_view。如果您还没有std::string_view,那么创建类似string_view 的包装器很容易。
  • 那么你不能使用vector,因为你需要给它一个不同的分配器类型,这是一个模板参数,因此会改变签名。
  • 你不能。容器通过设计管理自己的内存。你想要一个视图而不是一个容器
  • 简短回答:你不知道。你创建你的向量,如果你需要访问原始指针,那么你可以做data()
  • @Logman 自定义分配器更改类型。 std::vector&lt;char&gt;std::vector&lt;char, AllocatorThatDoesntAllocate&gt;不兼容,此时你不妨使用string_view

标签: c++ vector stl


【解决方案1】:

std::vector 被设计为专门拥有它所保存的数据,因此进行内存复制是 std::vector 工作的唯一安全方式。这只会留下不安全的黑客攻击。如果我们可以假设该函数不会改变向量大小,则可以滥用 std::vector。在我的编译器中(在 g++4.8 和 cpp.sh 上测试)std::vector 被实现为三个指针(开始数据,结束使用的数据和结束分配),因此我可以滥用向量:

#include <vector>
#include <iostream>

void myLibFunc( std::vector< char > & a )
{
    for( char c : a )
    {
        std::cout << '[' << c << ']';
    }
    a[0] = 'B'
    std::cout << '\n';
}

void myFunc(char *buffer,int bufferSize)
{
   std::vector<char > mydata;
   // cast to alterable pointers, cast should also keep 
   // mydata in scope until after the last assignment.
   char ** abuser = (char**)&mydata;
   // save old values and substitute new values
   char *tmp0 = abuser[0];
   abuser[0] = buffer;
   char *tmp1 = abuser[1];
   abuser[1] = buffer+bufferSize;
   char *tmp2 = abuser[2];
   abuser[2] = buffer+bufferSize;
   myLibFunc(mydata);
   // return old values to avoid crash when mydata goes out of scope.
   abuser[0] = tmp0;
   abuser[1] = tmp1;
   abuser[2] = tmp2;
}

int main()
{
    char p[] = "Hello World";
    myFunc( &p[0] + 2, 5 );
    std::cout << p << '\n';
    return 0;
}

请注意,这种滥用可能是不可移植的,并导致无法解释的崩溃。

【讨论】:

  • 这也是我的版本:this(对那些认为这是对 C++ 的残酷对待的人没有冒犯)
【解决方案2】:

如果您不能更改函数的签名,则没有副本是不可能的。

但更好的方法是考虑您的界面。如果你在随机访问迭代器上构建myLibFunc,你的问题就解决了:

template <class CharRandomAccessIterator>
 myLibFunc(CharRandomAccessIterator& begin, CharRandomAccessIterator& end )
 {
     // dosomthing with data
     size = end - begin;
     begin[xyz]; // access elements
 }
 myFunc(char *buffer,int bufferSize)
 {
       std::vector<char > mydata(buffer,buffer+bufferSize);
       myLibFunc(mydata.begin(), mydata.end()); // This will work
       myLibFunc(buffer, buffer+size); // This will work too
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多