cf *_*ica 3 c++ standards winapi c++11
是否有按值传递类的标准过程?换句话说,如果我这样做:
struct Test
{
int a;
double b;
}
void DoSomething(Test t)
{
std::cout << t.a << std::endl;
std::cout << t.b << std::endl;
}
//...
Test myObj;
myObj.a = 5;
myObj.b = 10.5;
DoSomething(myObj);
Run Code Online (Sandbox Code Playgroud)
假设标准打包和布局,标准是否提供任何保证,无论编译器如何,都将以一致的方式发送和接收类?
因为我预期会有"你为什么要这样做?"的问题.或者"感觉就像一个XY问题",这是(冗长的)背景.我试图在EXE和用不同编译器编译的DLL之间来回传递一个类对象,看起来没有从正确的起始地址读取类对象.但是,如果我通过引用传递对象,这个问题就会消失.(奖金问题 - 为什么通过参考工作时传递值不会?我在传递值的印象下会复制对象并传递对副本的引用.显然我在这里误解了一些东西.)
通常,不同C++编译器之间的ABI可以以他们认为合适的任何方式变化.C++标准不要求给定的ABI.
但是,C ABI非常稳定.解决此问题的一种方法是使用仅限头的函数将代码转换extern "C"为从DLL导出的函数.在DLL中,extern "C"函数会调用更传统的C++接口.
举一个具体的例子,
struct Test;
// DLL exported:
extern "C" void Private_DoSomething_Exported( Test* );
// Interface:
namespace Interface {
inline void DoSomething( Test t ) { return Private_DoSomething_Exported(&t); }
};
// implementation. Using Test&& to make it clear that the reference is not an export parameter:
namespace Implementation {
void DoSomething( Test&&t ) {
std::cout << t.a << std::endl;
std::cout << t.b << std::endl;
}
}
void Private_DoSomething_Exported( Test* t ) {
Assert(t);
Implementation::DoSomething(std::move(*t));
}
Run Code Online (Sandbox Code Playgroud)
这将"最兼容"的ABI(纯粹的"C"ABI)置于从DLL导出函数的位置.客户端代码调用Interface::DoSomething,inline在客户端代码中调用"C"ABI(它甚至不知道对象的布局),然后调用C++ Implementation::DoSomething.
这仍然不能证明每个问题,因为甚至POD结构的布局也可能因编译器而异(作为一个实际例子,一些编译器long在64位机器上视为32位,其他编程器在64位机器上long视为64位).包装也可能有所不同.
为了减少这种影响,您首先要仅使用C头文件中的固定大小类型.您还需要检查两个编译器的打包文档.
| 归档时间: |
|
| 查看次数: |
386 次 |
| 最近记录: |