【问题标题】:Return pointer to vector's data without copying buffer and memory leaks在不复制缓冲区和内存泄漏的情况下返回指向向量数据的指针
【发布时间】:2017-05-10 12:27:07
【问题描述】:

这个问题应该很简单,但我不是 C++ 程序员。

想象一下,我有一个std::vector,其中填充了函数中的局部变量。我想做的是返回指向该数据的指针并从该函数中计数,而不是向量本身(因为它转到另一种语言,而不是 C++)。那么最好的方法是什么?

我敢打赌我可以用new 关键字声明向量,但是当我稍后在其pointer data 上调用free() 时,会不会有泄漏?

我也可以malloc() 新缓冲区,将向量的缓冲区复制到其中并返回新的缓冲区,但我希望我可以避免这种情况。

【问题讨论】:

  • 如何将数据发送到其他语言?您可以只返回向量本身,然后使用v.data() 发送返回向量的内部指针吗?
  • vector 必须存在于其他语言使用它的地方。您要么不需要在其他语言完成之前从函数返回,要么将vector 移动到某个持久空间中,或者将保持vector 活动的责任交给其他语言。这些解决方案中的任何一个都可以,但是您的问题没有包含足够的信息来知道哪个是合适的。
  • mallocfreenewdelete。不要越过那些溪流。并且不要试图从它的眼皮底下删除vector的数据;这不好。
  • 在函数外声明向量。将向量上的指针或链接传递给函数。填充函数内部的向量。你不需要调用“new”/“delete” - 向量正在做它而不是你;)

标签: c++ pointers vector memory-leaks


【解决方案1】:

您可以使用std::vector<T>& 作为参数声明您的函数,并仅返回vector.count()(请参阅Pass by reference in C++)。稍后,在客户端代码中将一个空的构造向量传递给该函数。

要获取指向原始数据的指针,您可以使用&vector[0]&vector.front()。从C++11开始,在vector中新增了一个成员函数:data(),返回容器中初始元素的地址。

一般情况下,不要使用不必要的malloc/free 操作,并避免在不必要时使用堆分配。考虑智能指针而不是原始指针和make_shared/make_unique而不是显式new

【讨论】:

  • std::pair<std::vector<T>, int>> 毫无意义。您已经可以使用vector.size()。你的意思是std::pair<int *, int>> 伪造array_viewspan
  • 啊,好吧,我认为计数不是向量的计数
  • 谢谢,所以基本上不可能做我想做的事!仍然赞成
【解决方案2】:

如果您的向量包含基本类型(例如 int)并且您知道内存将被释放释放,您可以使用:

if(v.empty()) return NULL;
int* retResut;
retResut= reinterpret_cast<int*>(std::malloc(v.size() * sizeof(int)));
std::memcpy(retResut,v.data(),v.size()* sizeof(int));
return retResut 

【讨论】:

  • 问题明确指出“没有内存泄漏”。
  • @nwp 来自原始问题:“但是当我稍后调用 free()”时,我认为稍后调用 free 是一种选择。
  • 这是我在问题本身中考虑的选项,但谢谢!据我所知,我的问题只有一个答案:“不可能”
【解决方案3】:

假设您需要声明一个具有以下定义的函数:SomeType* foo();。您可以使用 std::vector::data 获取指向数据的原始指针 (c++11)。在 c++03 的情况下,您可以使用 &amp;my_vector[0](并且您必须检查空向量以避免运行时调试断言)

需要考虑一件事;它是从多个调用的 线程与否:

  1. 当你只有一个线程调用foo:

    std::vector<SomeType>& get_buffer()
    {
        static std::vector<SomeType> data;
        return data;
    }
    SomeType* foo()
    {
        std::vector<SomeType>& buffer = get_buffer();
        buffer.clear();
    
        //fill buffer with stuff with push_back
    
        return buffer.data();
    }
    
  2. 当从多个线程调用时。静态变量是 initialized properly 但是 push_back 函数不是线程安全的。您还需要为每个线程使用不同的缓冲区,但这并不能保证总安全(考虑到您无法知道该数据的生命周期应该有多长)。 get_buffer 应该为每个线程返回一个唯一的 std::vector。您可以通过将static 更改为thread_local 来使用thread local storage(参见this):

    std::vector<SomeType>& get_buffer()
    {
        thread_local std::vector<SomeType> data;
        return data;
    }
    

    thread_local 是自 c++11 的节点如果您使用的是 c++03,则需要使用 boost 库或平台特定代码。

【讨论】:

    猜你喜欢
    • 2019-04-18
    • 2012-09-08
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    相关资源
    最近更新 更多