如果这是错误的网站,请提前告知,如果有,请告诉我们。
我编写了一个函数,用于检查特定std::map
中是否存在键,并想知道这是否是一个很好的做法,并且,是否有人可以抛出任何关于改进的指示。
std::map
允许为值接受多种数据类型。
union Variants {
int asInt;
char* asStr;
Variants(int in) { asInt = in; }
Variants() { asInt = 0;}
Variants(char* in) { asStr = in; }
operator int() { return asInt; }
operator char*() { return asStr; }
};
template<typename T, typename Y>
bool in_map(T value, std::map<T, Y> &map)
{
if(map.find(value) == map.end()) {
return false;
}else{
return true;
}
}
然后我可以主要使用以下内容:
std::map<string, Variants> attributes;
attributes["value1"] = 101;
attributes["value2"] = "Hello, world";
if(in_map<std::string, Variants>("value1", attributes))
{
std::cout << "Yes, exists!";
}
非常感谢任何帮助或建议。对不起,如果这不符合规则或标准。谢谢!
答案 0 :(得分:3)
我看到你的函数最大的问题是你丢弃了生成的迭代器。
当您检查地图中是否存在某个键时,大多数情况下您希望在此之后检索/使用相关值。在这种情况下使用您的函数会强制您以性能为代价进行双重查找。我只是完全避免使用该函数,并直接编写测试,保留迭代器以供以后使用,以避免无用的查找:
auto it = map_object.find("key");
if (it != map_object.end())
use(it->second);
else
std::cout << "not found" << std::endl;
当然,如果您只是检查一个密钥是否存在而不关心相关值,那么您的功能很好(考虑到其他人在评论中告诉您的内容)但我认为其用例非常有限并不值得额外的功能。你可以这么做:
if (map_object.find("key") != map_object.end())
std::cout << "found, but I don't care about the value" << std::endl;
答案 1 :(得分:0)
关于改进的指示。
确定。
template<typename T, typename Y>
bool in_map(T value, const std::map<T, Y> &map)
{
return map.find(value) != map.end();
}
我将地图作为第一个参数(只是一个偏好)。另外,因为整个东西都适合单行,你可能甚至不需要这个功能。
你也扔掉了返回的迭代器,但既然你没有使用它,那不是问题。
除此之外,这在编码实践方面看起来还不错吗?即使用Union还是我可以使用的其他类型如struct?
好吧,使用char*
并不是一个好主意,因为char*
暗示您可以修改数据。 char*
也暗示此指针是动态分配的,您可能希望稍后delete[]
该指针。你不能在工会中使用析构函数。如果无法更改文本,则可以使用const char*
,否则您可能希望使用不同的数据类型。另请参阅Rule of Three
下一个问题 - 您正在尝试将char *和int放在同一位置。这意味着在某些时候你试图将指针转换为整数。这是一个坏主意,因为在64位平台上,指针可能不适合int,而你只能得到它的一半。
此外,如果您尝试在同一个变量中存储多个不同的值,则不会指示哪个类型存储在任何位置。要做到这一点,你需要将union括在struct中并添加指示存储对象类型的字段(到struct)。但是,在这种情况下,你最终会重新发明轮子。因此,如果您尝试存储“通用”类型,则可能需要查看Boost.Any,Boost.Variant或QVariant。但所有这些都需要BIG外部库(boost或Qt)。
答案 2 :(得分:0)
输入
if(in_map<std::string, Variants>("value1", attributes))
对我来说似乎有些过分,键入所有typename语法让我只想使用map.find
函数而不仅仅是为了方便。但是,根据您的编译器,有时可以自动解释模板参数,例如,visual studio将允许这样:
if(in_map(std::string("value1"), attributes))
在这种情况下,我必须构造一个std::string
对象来替换char*
,但我已经从调用中完全删除了模板定义,编译器仍然会找出{{1} }和T
基于给定的参数。
但是,我建议的建议是使用Y
来定义您的“功能”。虽然它不是真正的函数,但由于#define
实际上只是直接将代码片段替换为源代码,因此它可以使事情变得更容易和视觉上吸引人:
#define
然后你使用它的代码就像这样:
#define in_map(value,map) (map.find(value) != map.end())
你们都得到了不使用函数调用的优化,以及像在PHP中那样的视觉外观。