如何从内存管理职责中释放标准字符串?
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::function
和 std::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
。
我有一个字符串值和一个接受字符指针和长度的函数,完成后调用回调,回调是在该函数调用上提供的 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::function
和 std::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
。