C++ 指针映射中的默认值nullptr是否已定义?
下面的代码似乎总是遵循真正的分支C++ 指针映射中的默认值nullptr是否已定义?,c++,c++11,big-o,time-complexity,C++,C++11,Big O,Time Complexity,下面的代码似乎总是遵循真正的分支 #include <map> #include <iostream> class TestClass { // implementation } int main() { std::map<int, TestClass*> TestMap; if (TestMap[203] == nullptr) { std::cout << "true"; } else { std::cou
#include <map>
#include <iostream>
class TestClass {
// implementation
}
int main() {
std::map<int, TestClass*> TestMap;
if (TestMap[203] == nullptr) {
std::cout << "true";
} else {
std::cout << "false";
}
return 0;
}
一种解决方案是,在检查
地图时,使用特殊函数提供默认值。然而,我的理解是,这将导致查找的复杂性为O(n)
,而不是O(1)
。在我的场景中,这并不是一个太大的问题(只有少数日志),但更好的解决方案是强制Log*
类型的指针在默认情况下引用nullptr
,从而使查找检查O(1)
同时可移植。这可能吗?如果可能,我将如何做?映射值总是初始化其成员(当然,在没有复制初始化的情况下),而内置类型的值初始化意味着零初始化,因此它确实是定义的行为。这对于使用操作符[]
访问元素时生成的新键的值部分尤其如此,调用该操作符之前不存在该元素
但是请注意,未序列化的指针不一定是空指针;事实上,仅仅读取它的值就已经调用了未定义的行为(在某些情况下,在某些平台上可能会出现分段错误)。关键是映射中的指针不是未初始化的。所以如果你写一个例子
void foo()
{
TestClass* p;
// ...
}
p
将不会初始化为nullptr
但是请注意,您可能希望检查是否存在,以避免累积不必要的条目。您可以使用find
成员函数检查是否存在:
map<int, TestClass*>::iterator it = TestMap.find(203);
if (it == map.end())
{
// there's no such element in the map
}
else
{
TestClass* p = it->second;
// ...
}
迭代器it=TestMap.find(203);
if(it==map.end())
{
//地图上没有这样的元素
}
其他的
{
TestClass*p=it->second;
// ...
}
是的,这是定义的行为。如果当您通过操作符[]
访问某个元素时,该元素尚未出现在地图中,那么它将被默认构造。感谢您的快速回答!为了进一步澄清,是否将“TestClass*p();”初始化为nullptr?@MrBushido No.TestClass*p()
不声明变量,它声明一个不带参数的函数,并返回TestClass*
.MrBushido:int*p代码>默认已初始化,因此具有不确定的值<代码>int*p{}
初始化为零,并且转换为指针的0始终是空指针常量,因此将与nullptr进行比较。答案是使用了错误的术语。如果操作符[]
中的新元素不存在,则std::map
将对其进行值初始化(而不是默认初始化)。请务必注意这一差异,因为POD类型的默认初始化使它们未初始化,而值初始化意味着相同类型的零初始化。在答案中出现默认初始化的地方替换值初始化将使其正确。相信我,我刚刚检查了这两个标准。在C++03中,T()
的描述在5.2.3p2中,表达式T(),其中T是非数组完整对象类型或(可能是cv限定的)void类型的简单类型说明符(7.1.5.2),创建指定类型的右值,该值初始化为*。C++11中的同一个引号读取*表达式T(),其中T是非数组完整对象类型或(可能是cv限定的)void类型的简单类型说明符或typename说明符,它创建指定类型的prvalue,该值已初始化
map<int, TestClass*>::iterator it = TestMap.find(203);
if (it == map.end())
{
// there's no such element in the map
}
else
{
TestClass* p = it->second;
// ...
}