VC++允许对STL容器使用const类型.为什么?

liz*_*isk 12 c++ stl const visual-c++-2008 visual-c++

STL容器要求存储的值可以复制构造和分配.const T显然不是任何T的可分配类型,但我试图使用它(只是好奇)并发现它编译,而且,表现为可分配类型.

vector<const int> v(1);
v[0] = 17;
Run Code Online (Sandbox Code Playgroud)

这在Visual Studio 2008中成功运行,并将v [0]分配给17.

Jam*_*lis 12

这不是其他人建议的实施中的错误.

违反C++标准库工具的要求不会导致程序格式错误,从而产生未定义的行为.

您违反了存储在容器中的值类型必须是可复制构造和可分配的要求(const显然类型不可分配),因此您的程序会显示未定义的行为.

可以在C++ 03 17.4.3.6 [lib.res.on.functions]中找到C++标准中适用的语言:

在某些情况下(替换函数,处理函数,用于实例化标准库模板组件的类型的操作),C++标准库依赖于C++程序提供的组件.如果这些组件不符合要求,则标准对实施没有要求.

特别是,在以下情况下,效果未定义:

...

  • 对于在实例化模板组件时用作模板参数的类型,如果该类型上的操作未实现适用的Requirements子句的语义.

Visual C++标准库实现可以对此代码执行任何操作,包括静默删除或忽略const限定,并且它仍然符合标准.

  • 在我最卑微的意见中,这里的沉默资格去除真的非常难看. (3认同)

Mat*_*lia 1

\n这根本不应该起作用。正如您所说,在 \xc2\xa723.1 \xc2\xb6 3 中指定了存储在容器中的对象必须是CopyConstructible(如 \xc2\xa720.1.3 中指定的那样)并且Assignable

\n\n

Assignable类型的要求是T:beingtuof typeT,您可以执行以下操作:

\n\n
t = u\n
Run Code Online (Sandbox Code Playgroud)\n\n

有一个T&作为返回值并且t等价于uas 后置条件。(\xc2\xa723.1\xc2\xb64)

\n\n

因此,const类型显然不是Assignable,因为这样做t = u会引发编译错误 (\xc2\xa77.1.5.1 \xc2\xb65)。

\n\n

我认为这是微软实施中的一个错误。如果您尝试实例化一个vector<const int>(使用和不使用-std=c++0x标志的情况下进行测试,以防万一)。

\n\n

顺便说一句,这在IBM FAQ中也有详细解释

\n\n
\n\n

理论上,正如 @James McNellis 所说,编译器不需要在向量实例化上崩溃(如果它是未定义的行为,任何事情都可能发生 - 包括一切正常);但是,在赋值语句中违反了标准,应该会产生编译错误。

\n\n

事实上,该operator[]成员返回一个vector<const int>::reference; 该值必须是T(\xc2\xa723.1 \xc2\xb65 表 66) 的左值;因为T是一种const类型,所以它将是一个const左值。因此,我们归结为 (\xc2\xa77.1.5.1 \xc2\xb65),它将尝试对元素执行赋值的代码定义为const“格式错误”,这需要一个编译错误或至少一个警告,因为分配给 -const是可诊断规则 (\xc2\xa71.4 \xc2\xb61-2) (未指定“无需诊断”语句)。\n

\n\n
\n\n

最终编辑

\n\n

事实上,@James McNellis 是对的;一旦您通过实例化调用了未定义的行为vector<const int>,通常的规则就不再有价值,因此无论它做什么,实现仍然符合标准 - 包括删除const从元素类型中删除 或生成通常的鼻恶魔。

\n