我有以下代码
size_t returnSize(const char* s)
{
string string(s);
return string.size();
};
size_t returnSize(const int& i)
{
return sizeof(i);
};
template<typename T>
vector<char> Serialize(const T& t)
{
T* pt = new T(t);
vector<char> CasttoChar;
for (int i =0 ;i<returnSize(t);i++)
{
CasttoChar.push_back(reinterpret_cast<const char*>(pt)[i]);
}
delete pt;
return CasttoChar;
};
template<typename T>
T DeSerialize(const vector<char> cstr)
{
T* a = (T*)(&cstr[0]);
return *a;
}
int _tmain(int argc, _TCHAR* argv[])
{
int x = 97;
vector<char> c = Serialize(x);
cout << DeSerialize<int>(c) << endl;
string k = "blabla";
vector<char> c3 = Serialize(k.c_str());
cout << DeSerialize<const char*>(c3) << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
//output is
//97
//blabla
此行T* a = (T*)(&cstr[0]);
是否安全?
此外,我尝试reinterpret_cast<T*>(&cstr[0]);
而不是T* a = (T*)(&cstr[0]);
,但编译器抱怨无法将const char *转换为int *。那么为什么C风格的演员呢?
答案 0 :(得分:3)
参考标准
为什么reinterpret_cast失败?
5.2.10重新解释cast [expr.reinterpret.cast]
reinterpret_cast运算符不应丢弃constness(5.2.11)。 整数,枚举,指针或指向成员的指针的表达式 type可以显式转换为自己的类型;这样的演员收益率 其操作数的值。
我应该使用C Cast吗? 没有。使用C Cast代替C ++ Cast总是不安全的。您正在尝试删除作为UB的Object的常量。 使用reinterpret_cast,实际上会捕获此错误,并在编译期间告知您潜在的陷阱。
在这种情况下,您应该实际使用const_cast
。它是将const
对象转换为非const
对象
但是为什么C Cast会起作用
引用问题When should static_cast, dynamic_cast and reinterpret_cast be used?
中接受的答案C样式演员被定义为以下第一个 成功:
const_cast static_cast static_cast, then const_cast reinterpret_cast reinterpret_cast, then const_cast
幸运的是,它先尝试const_cast
。
答案 1 :(得分:2)
C风格的演员表是有效的,因为它需要很多步骤才能使演员成功。它使用以下第一个成功:
const_cast
static_cast
static_cast + const_cast
reinterpret_cast
reinterpret_cast + const_cast
在这种情况下,它正在进行最“强大”的演员,reinterpret_cast
到const int *
,然后是const_cast
到int*
。
单独reinterpret_cast
无法编译,因为你正在抛弃常量。 const_cast
需要投放到int*
。然而,对reinterpret_cast
进行const int*
会很好。
顺便说一句,你正在做的事情通常是不安全的,除非你使用编译器扩展来确保你反序列化的任何用户定义类型都没有填充。
答案 2 :(得分:0)
c ++中的C样式转换不是一个好主意,因为你经过了阻止你删除const或任意更改类型的检查。如果你想使代码按原样运行,首先需要const_cast然后reinterpret_cast,但真的尝试避免const转换。要使用reinterpret_cast避免警告,只需声明为const T*
。
答案 3 :(得分:0)
坚持使用C ++演员。 reinterpret_cast
没有工作的原因是你扔掉了constness,这并不酷;你必须使用const_cast
,你就不应该这样做。 C演员忽略了这一点。
话虽如此,你想在这里实现什么?您已经有效地转换为char
数组和memcpy
而没有带来的效率。
答案 4 :(得分:0)
很抱歉在这里发出声响,但你的代码在几个方面被破坏了,而且这些代码只是其中之一。关于转换,只要你使用转换from / to vector就不仅仅是一个简单的int或者需要一个构造函数,它就会失败。无论如何,从char const*
到void const*
到T const*
的两步转换很遗憾是必要的。
现在,其他问题:
DeSerialize<char const*>()
返回指向char的指针。这个指针指向由给定向量拥有的内存,该值由值传递,并且从该函数返回后不再存在!它似乎很有运气。char const*
,也要考虑现在拥有该内存的人。关键是这个拥有者还必须释放内存。请考虑使用std::string
并使char const*
变体不使用模板的特化进行编译。