如何在C++中实现非构造函数的指定内存地址调用?
如何在C++中实现非构造函数的指定内存地址调用?
咱们先拆解一下你遇到的问题核心:C代码里可以直接调用接收指针参数的函数,把结果直接写到指定内存;但对应的C函数是返回对象的形式,现在要在标准C里模拟这种“把结果写入未初始化内存”的行为,同时和你给的C代码语义完全对齐。
下面是通用的标准C++解决方案,直接替换你代码里的/* what? */即可:
#include <new> #include <utility> // 引入std::move做优化 class external_class{ public: external_class(); ~external_class(); unsigned short data; }; external_class external_function(); extern "C" void construst_external_class_at(external_class *out){ new(out) external_class; } extern "C" void return_external_function_at(external_class *out){ // 在指定内存上移动构造external_function返回的对象 new(out) external_class(std::move(external_function())); }
为什么这么写?
- placement new的必要性:
out指向的是未初始化的原始内存,不能直接赋值(赋值要求左操作数是已经构造好的对象),所以必须用placement new在这块内存上构造对象——这和你用placement new调用构造函数的逻辑完全一致。 - std::move的优化作用:
external_function()返回的是临时对象,用std::move可以把这个临时对象的资源“转移”给新构造的对象,避免无意义的深拷贝(如果你的类定义了移动构造函数,就会走移动逻辑;没定义的话会自动 fallback 到拷贝构造,语义也是安全的)。 - 可移植性拉满:这个写法完全遵循C++标准,不依赖任何编译器/ABI的私有细节,比直接调用底层的ABI函数靠谱多了。
针对特殊场景的优化写法
如果你的external_class是平凡可拷贝类型(比如只有基本数据成员,没有自定义的构造/拷贝/移动/析构函数),还可以用std::memcpy来做更高效的内存拷贝:
#include <new> #include <cstring> // ... 其他代码不变 ... extern "C" void return_external_function_at(external_class *out){ auto temp = external_function(); std::memcpy(out, &temp, sizeof(external_class)); }
但注意:这种写法只适用于平凡可拷贝类型,如果类里有虚函数、动态分配的内存或者其他非平凡成员,用memcpy会直接破坏对象的内部状态,导致未定义行为,所以通用场景下优先选第一种placement new的写法。
最后提个关键注意事项
和placement new创建的所有对象一样,当你不再需要out指向的对象时,得手动调用析构函数(如果类有非平凡析构的话):
out->~external_class();
不然会导致资源泄露哦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

