向量包含指向无效内存的指针是非法的
这就是标准对容器内容的规定:
(23.3) : 这些组件中存储的对象类型必须满足CopyConstructible类型 (20.1.3) 的要求,以及Assignable类型的附加要求。
(20.1.3.1,CopyConstructible):在下表 30 中,T 是由实例化模板的 C++ 程序提供的类型,t 是 T 类型的值,u 是 const T 类型的值。
expression return type requirement
xxxxxxxxxx xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
T(t) t is equivelant to T(t)
T(u) u is equivelant to T(u)
t.~T()
&t T* denotes the address of t
&u const T* denotes the address of u
(23.1.4, Assignable):64,T是用于实例化容器的类型,t是T的值,u是(可能是const)T的值。
expression return type requirement
xxxxxxxxxx xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
t = u T& t is equivilant to u
这就是关于 STL 集合内容的全部内容。它对指针只字未提,并且对指向有效内存的指针特别沉默。
因此,delete
在 a 中插入指针vector
,虽然很可能是一个非常糟糕的架构决策,并且在周六晚上 3:00 AM 调试器会带来痛苦和折磨,但它是完全合法的。
编辑:
关于 Kranar 的评论“将指针分配给无效的指针值会导致未定义的行为”。不,这是不正确的。此代码完全有效:
Foo* foo = new Foo();
delete foo;
Foo* foo_2 = foo; // This is legal
非法的是试图用那个指针做某事(或者foo
,就此而言):
delete foo_2; // UB
foo_2->do_something(); // UB
Foo& foo_ref = *foo_2; // UB
根据标准,简单地创建一个野指针是合法的。可能不是一个好主意,但仍然合法。
编辑2:
更多关于指针类型的标准。
标准(3.9.2.3)这么说:
...对象指针类型的有效值表示内存中字节的地址(1.7)或空指针(4.10)...
...以及关于“内存中的一个字节”(1.7.1):
C++ 内存模型中的基本存储单元是字节。一个字节至少大到足以包含基本执行字符集的任何成员,并且由连续的位序列组成,其数量由实现定义。最低有效位称为低位;最高有效位称为高位。C++ 程序可用的内存由一个或多个连续字节序列组成。每个字节都有一个唯一的地址。
这里没有关于那个字节是生活的一部分Foo
,关于你可以访问它,或者任何类似的东西。它只是内存中的一个字节。