【发布时间】:2011-03-25 17:37:59
【问题描述】:
是否可以在 C++ 中将字符数组转换为像这样的对象:
char* bytes = some bytes...
MyObject obj = (MyObject)(bytes);
?
我必须如何定义强制转换运算符?
谢谢:)
【问题讨论】:
标签: c++ casting operator-overloading
是否可以在 C++ 中将字符数组转换为像这样的对象:
char* bytes = some bytes...
MyObject obj = (MyObject)(bytes);
?
我必须如何定义强制转换运算符?
谢谢:)
【问题讨论】:
标签: c++ casting operator-overloading
您可能想为 MyObject 定义一个构造函数:
class MyObject {
public:
explicit MyObject(const char* bytes);
...
};
MyObject::MyObject(const char* bytes) {
// do whatever you want to initialize "MyObject" from the byte string
}
然后你就可以使用它了:
char* bytes = some bytes...
MyObject obj = MyObject(bytes); // this will work
MyObject obj(bytes); // so will this
【讨论】:
MyObject obj = bytes;。我建议在构造函数上使用explicit 关键字来防止这种情况,它可以避免一些令人惊讶的错误。
explicit 对于单参数构造函数来说是一个非常好的主意。我已经更新了我的答案。
std::string 的构造函数不是explicit 并且符合我们的预期。
我可以在这里看到两种可能性。如果您知道代表目标类型的数据,则可以使用reinterpret_cast 将它们视为该类型的对象:
MyObject *obj = reinterpret_cast<MyObject *>(bytes);
如果要在指定内存中创建指定类型的对象,使用placement new操作符在指定地址构造对象:
char *bytes = whatever;
MyObject *obj = new(bytes) MyObject;
当你使用完对象时,你不要delete它,你直接调用dtor:
obj->~MyObject();
请注意,要使其正常工作,您需要确保(如果没有别的)bytes 指向与目标类型正确对齐的数据。
【讨论】:
MyObject * 投射而你现在只是把它投射回来?)那么 larsmans 的答案就是要走的路。
reinterpret_cast,而不是static_cast。
如果字节串实际上代表MyObject类型的有效对象,你可以得到一个MyObject*
reinterpret_cast<MyObject *>(bytes)
(但这不太可能起作用,除非char* 是一个指向正确构造的MyObject 的指针的结果。)
【讨论】:
char * & 取消引用结果免于别名。没有相反的余地。但只要指针不在同一范围内取消引用——当然没有理由这样做——那么别名甚至不会进入等式。这与允许“往返”转换指针并确保转换A * => B * => A * 在两边保留相同的A * 的规则相同/遵循。如果一个人甚至不能在没有别名的情况下转换对象的地址,这是不可能的。别名仅指 dereferenced 指针,即 lvalues。
char* 是指向正确构造的MyObject 的指针的结果" => +1。该标准非常清楚,只有不兼容指针类型之间的reinterpret_cast 的“往返”形式具有定义的结果。其他任何东西都是 UB,并拼命希望你的编译器能做你认为它应该做的事情。将任意字节转换为某个对象的正确方法 - 假设它是可简单复制的,因为它必须是 - 是从 char 缓冲区分配一个实例和 memcpy() 到它。哎呀,好的优化器可以渲染到与演员相同的代码,但无需调用 UB
我喜欢 Jerry Coffin 和 larsman 的回答,这取决于所讨论的位置是否已经有构造对象。
不过还有一个问题。如果MyObject 的类型恰好符合POD class 的条件,那么可以像larsman 建议的那样对指针使用reintreprent 强制转换,因为该对象实际上不需要构造函数。
我说“可能”是因为您的平台很可能对char * 和类指针使用不同的表示。不过,我用过的大多数都不会这样做。
【讨论】:
T,可能比编译器无法验证的char 具有更严格的对齐方式。我非常确信它确实不允许允许这样做——除非所讨论的char * 最初来自有效分配的T *——并且其他任何东西都是正式的UB。看到这条评论:stackoverflow.com/questions/5436092/…
char 数组并返回并保留相同的值 - 实际上不发出任何构造函数代码,标准仍然要求此类对象具有明确定义的生命周期。这大概意味着编译器必须看到代码说“在这块内存中创建一个struct T”,否则所有的赌注都关闭了,意味着它可以发出不安全的代码或优化尝试。正如您在这里非常模糊地推荐的那样,大多数编译器都允许任意转换,但这并不意味着它不是 UB。