reinterpret_cast 在 std::unordered_map 之间
reinterpret_cast between std::unordered_map
我有以下 unordered_map
s:
struct a{
std::string b;
};
int main()
{
std::unordered_map<std::string, std::string> source;
source["1"] = "Test";
source["2"] = "Test2";
std::unordered_map<std::string, a> dest = *reinterpret_cast<std::unordered_map<std::string, a>*>(&source);
std::cout << dest["1"].b << std::endl;
std::cout << dest["2"].b << std::endl;
}
使用 reinterpret_cast
我将 source
转换为 dest
。这是有效的,因为 struct a
只包含一个 std::string
.
我的问题:这实际上是一种好的做法吗? GCC 产生以下警告:
dereferencing type-punned pointer will break strict-aliasing rules
我可以安全地忽略它吗?或者仅转换 STL 容器的原始字节是否有任何潜在的缺点?
不,那是不是好的做法。您的代码不安全。事实上恰恰相反:未定义的行为,这意味着有时它会起作用有时它不会,即使没有告诉你。
真正的问题 是您没有"legal" 方法将std::string
转换为struct a
。这不是 C,不要将东西用作普通字节,而是使用语言的类型系统。然后编译器会帮你避免严重的错误。
这是我的解决方案:
#include <unordered_map>
#include <string>
#include <iostream>
#include <algorithm>
struct a {
std::string b;
a () = default;
a (const std::string& b) : b(b){}
};
int main() {
std::unordered_map<std::string, std::string> source;
source["1"] = "Test";
source["2"] = "Test2";
std::unordered_map<std::string, a> dest;
std::transform(source.cbegin(),source.cend(),std::inserter(dest,dest.end()),[](const auto& value)
{
return std::forward_as_tuple(value.first,value.second);
});
std::cout << dest["1"].b << std::endl;
std::cout << dest["2"].b << std::endl;
}
如果您有性能方面的顾虑,您还可以添加一个移动构造函数等,但请相信我,可读的干净代码是快速的代码。否则,bootle neck 不是非铸造代码,而是使用地图、复制而不是移动等东西。但不要过早优化。
我有以下 unordered_map
s:
struct a{
std::string b;
};
int main()
{
std::unordered_map<std::string, std::string> source;
source["1"] = "Test";
source["2"] = "Test2";
std::unordered_map<std::string, a> dest = *reinterpret_cast<std::unordered_map<std::string, a>*>(&source);
std::cout << dest["1"].b << std::endl;
std::cout << dest["2"].b << std::endl;
}
使用 reinterpret_cast
我将 source
转换为 dest
。这是有效的,因为 struct a
只包含一个 std::string
.
我的问题:这实际上是一种好的做法吗? GCC 产生以下警告:
dereferencing type-punned pointer will break strict-aliasing rules
我可以安全地忽略它吗?或者仅转换 STL 容器的原始字节是否有任何潜在的缺点?
不,那是不是好的做法。您的代码不安全。事实上恰恰相反:未定义的行为,这意味着有时它会起作用有时它不会,即使没有告诉你。
真正的问题 是您没有"legal" 方法将std::string
转换为struct a
。这不是 C,不要将东西用作普通字节,而是使用语言的类型系统。然后编译器会帮你避免严重的错误。
这是我的解决方案:
#include <unordered_map>
#include <string>
#include <iostream>
#include <algorithm>
struct a {
std::string b;
a () = default;
a (const std::string& b) : b(b){}
};
int main() {
std::unordered_map<std::string, std::string> source;
source["1"] = "Test";
source["2"] = "Test2";
std::unordered_map<std::string, a> dest;
std::transform(source.cbegin(),source.cend(),std::inserter(dest,dest.end()),[](const auto& value)
{
return std::forward_as_tuple(value.first,value.second);
});
std::cout << dest["1"].b << std::endl;
std::cout << dest["2"].b << std::endl;
}
如果您有性能方面的顾虑,您还可以添加一个移动构造函数等,但请相信我,可读的干净代码是快速的代码。否则,bootle neck 不是非铸造代码,而是使用地图、复制而不是移动等东西。但不要过早优化。