败犬日报 2024-10-18
1. c 如何提供接口让 cpp 传 lambda 进去
提供 void* context, void(*func)(void*)
接口,类似 FunctionRef,有一些 C 库就是这样干的。
示例:
cpp
#include <functional>
#include <iostream>
void registerCallback(void* context, void (*func)(void*)) { func(context); }
struct Content {
std::function<void()> bind;
static void call(void* self) { static_cast<Content*>(self)->bind(); }
};
int main() {
int x = 233;
auto lambda = [x]() { std::cout << x << std::endl; };
Content content{lambda};
registerCallback(&content, Content::call);
return 0;
}
更进一步,想要消除 function 分配堆内存开销,以及 C 函数内也需要上下文,示例如下:
cpp
#include <iostream>
// C 接口,参数为回调函数和上下文
extern "C" void c_world(void (*func)(void*, void*), void* context) {
const char* msg = "world";
func(&msg, context);
}
// 适配 C 接口,允许传入 C++ 仿函数
template <typename Func>
void invoke_c_style(void (*c_func)(void (*)(void*, void*), void*), Func f) {
auto callback = [](void* data, void* context) {
auto& func = *static_cast<Func*>(context);
func(data);
};
c_func(callback, &f);
}
int main() {
std::string message = "Hello, ";
invoke_c_style(c_world, [&](void* c_msg) {
std::cout << message << *static_cast<const char**>(c_msg) << "!\n";
});
}
2. 类外能重载赋值运算符吗
不行。
不行的原因可能是,类有默认的赋值运算符,容易出现歧义。
3. 并行优化好多都在 O3(编译选项)里面
空间优化是 Os。
4. void func(const std::shared_ptr &ptr) 写法好吗
没有明显的缺点。
5. 把 double tostring 再转回来,这个误差会有多大
测试结果看起来就是保留 6 位小数(但是 cppref 没说)。这样的话,数字小相对误差就会很大。
cpp
#include <cstdio>
#include <string>
int main() {
double d = 0.00000114514;
printf("%.20f\n", d);
std::string s = std::to_string(d);
printf("%s\n", s.c_str());
d = std::stod(s);
printf("%.20f\n", d);
return 0;
}
输出是:
text
0.00000114514000000000
0.000001
0.00000100000000000000