【问题标题】:How to release std string from memory management duties?如何从内存管理职责中释放标准字符串?
【发布时间】:2015-04-20 09:56:15
【问题描述】:

我有一个按值表示的字符串和一个接受 char 指针和长度的函数,完成后调用一个回调,该回调是该函数调用上提供的 lambda 表达式。我希望我的字符串数据在该回调上被释放 - 而不是在范围退出时。在 c++11 中没有进入 lambda,并且我发现当前的包装器实现不能作为 void(*fun)() 函数参数传递。有没有办法在 c++11 中移动字符串或将其从内存职责中释放?

原来的 API 在 C 中

void Send(const void * _topic, int length, void (*OnSend)());

在发送数据后激活其他发送者线程并调用 OnSend。零拷贝是这一切的重点。

我想从 C++ 中调用它并将其移入一个真正的字符串,保持零拷贝。

最终用 C++ 重写核心 API - 在没有 Pools/const size Ring 缓冲区的情况下从 C 中做这样的事情真的很难!所以拥有std::functionstd::bind 一切都会变得简单得多。然而现在 C API 包装了 C++ 一个...

而 C++ 部分看起来像这样:

void Send(std::string && _data) {
    const auto data_ptr = &_data;

    std::function<void()> OnDataRemoval = std::bind(
        [](std::string && d){},
            std::move(_data)
    );

     Send(data_ptr, OnDataRemoval);
}

【问题讨论】:

  • 从另一个线程调用回调
  • 你能发布示例代码吗?
  • 你的设计听起来很糟糕。如果您希望任何时候都可以解除分配,请使用带有指向它的指针的动态分配的对象。 (没有改变这个对象的内部)
  • 没有保证的方法可以让 std::string 在它的生命周期结束之前释放它的内存,如果这就是你要问的。但是,这可能有效:s.swap( std::string{} );。 BTW“回调是从另一个线程调用的”非常可疑,这真的是你的设计吗?如果函数在回调发生之前退出会发生什么?
  • “如果函数在回调发生之前退出会发生什么”这就是我想要解决的问题 - 一个函数在回调之前很久就退出了,因此字符串应该从它的内存义务中释放出来,否则我会被破坏记忆(

标签: c++ string c++11 memory


【解决方案1】:

由于您的字符串必须超过调用函数的范围,因此将其生命周期与该特定范围绑定是没有意义的。

这意味着你应该动态分配你的字符串:

#include <iostream>
#include <memory>
#include <future>

void    func(const char *str, int length, std::function<void()> callback)
{
  std::async
    (std::launch::async,
     [str, length, callback]
     {
       for (int i = 0; i < length; ++i)
         std::cout << str[i];
       std::cout << std::endl;

       callback();
     });
}

int     main(void)
{
  std::shared_ptr<std::string>   str = std::make_shared<std::string>("test");

  func(str->c_str(), str->length(),
       [str]
       {
         std::cout << "callback" << std::endl;
       });
}

您可以想象使用广义 lambda 捕获的更好解决方案,但由于您仅限于 c++11,因此您无法使用它

【讨论】:

    【解决方案2】:

    我认为你错了。回调不太可能必须是 lambda。这是operator() 的未命名类型。回调无法检测到名称,因此 named 仿函数也可以工作:

    void foo(std::string s)
    {
       struct functor { std::shared_ptr<std::string> data; operator()() const {/*NOP*/} };
       functor F { std::make_shared<std::string>(std::move(s)) };
       callback(F.data->c_str(), F.data->size(), std::move(F));
    }
    

    请注意,std::move(F) 只是必需的,因为为了清楚起见,我们将其命名为 functor F

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-11
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      • 2011-10-22
      • 1970-01-01
      相关资源
      最近更新 更多