如何从内存管理职责中释放标准字符串?

How to release std string from memory management duties?

我有一个字符串值和一个接受字符指针和长度的函数,完成后调用回调,回调是在该函数调用上提供的 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 大小的环形缓冲区的情况下从 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);
}

由于您的字符串必须比调用函数的作用域更长,因此将其生命周期与特定作用域联系起来没有意义。

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

#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,您不能使用那个

我想你错了。回调不太可能必须是 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