gpt4 book ai didi

c++ - 是否有按值传递类对象的标准程序?

转载 作者:太空狗 更新时间:2023-10-29 20:40:48 25 4
gpt4 key购买 nike

是否有按值传递类的标准程序?换句话说,如果我这样做:

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);

假设采用标准打包和布局,该标准是否提供任何保证,无论编译器如何,类都将以一致的方式发送和接收?


因为我预计会出现类似“您为什么要这样做?”这样的问题。或“这感觉像是一个 XY 问题”,here's (lengthy) context .我试图在用不同编译器编译的 EXE 和 DLL 之间来回传递类对象,但似乎没有从正确的起始地址读取类对象。但是,如果我通过引用传递对象,这个问题就消失了。 (额外的问题 - 为什么按值传递时按引用传递不起作用?我的印象是按值传递会复制对象并将引用传递给拷贝。显然我在这里误解了一些东西。)

最佳答案

一般来说,不同 C++ 编译器之间的 ABI 可以以他们认为合适的任何方式变化。 C++ 标准不强制要求给定的 ABI。

但是,C ABI 非常稳定。处理此问题的一种方法是使用仅 header 函数将您的代码转换为从 DLL 导出的 extern "C" 函数。在您的 DLL 中,extern "C" 函数然后调用更传统的 C++ 接口(interface)。

举个具体的例子,

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));
}

这会将“最兼容”的 ABI(纯“C”ABI)放置在您从 DLL 导出函数的位置。客户端代码调用 Interface::DoSomething,客户端代码中的 inline 调用 "C" ABI(它甚至不知道对象的布局),然后调用 C++ Implementation::DoSomething

这仍然不能证明所有问题,因为甚至 POD 结构的布局也可能因编译器而异(作为一个实际示例,一些编译器在 64 位机器上将 long 视为 32 位,其他在 64 位机器上将 long 视为 64 位)。包装也可能不同。

为了减少这种影响,您首先希望仅使用 C 头文件中的固定大小类型。您还需要检查两个编译器的打包文档。

关于c++ - 是否有按值传递类对象的标准程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22676050/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com