STL容器要求存储的值可以复制构造和分配。 const T显然不是任何T的可赋值类型,但我试图使用它(只是好奇)并发现它编译,而且,表现为可赋值类型。
vector<const int> v(1);
v[0] = 17;
这在Visual Studio 2008中成功运行,并将v [0]分配给17.
答案 0 :(得分:12)
这不是其他人建议的实施中的错误。
违反C ++标准库工具的要求不会导致程序格式错误,从而产生未定义的行为。
您违反了存储在容器中的值类型必须是可复制且可分配的要求(显然,const
类型不可分配),因此您的程序会显示未定义的行为。
C ++标准中适用的语言可以在C ++ 03 17.4.3.6 [lib.res.on.functions]中找到:
在某些情况下(替换函数,处理函数,用于实例化标准库模板组件的类型的操作),C ++标准库依赖于C ++程序提供的组件。如果这些组件不符合要求,则标准对实施没有要求。
特别是,在以下情况下效果未定义:
...
- 用于实例化模板组件时用作模板参数的类型,如果该类型的操作未实现适用的Requirements子句的语义。
Visual C ++标准库实现可以对此代码执行任何操作,包括静默删除或忽略const限定,并且它仍然符合标准。
答案 1 :(得分:1)
这根本不应该奏效。在§23.1¶3中,如你所说,它被指定存储在容器中的对象必须是 CopyConstructible
(如§20.1.3所述)和Assignable
。
类型Assignable
的{{1}}要求是T
和t
u
,您可以这样做:
T
以t = u
作为返回值,T&
相当于t
作为后置条件。 (§23.1¶4)
因此,u
类型显然不是const
,因为执行Assignable
会引发编译错误(第7.1.5.1节)。
我认为这是Microsoft实施中的一个错误。如果您尝试实例化t = u
(使用和不使用vector<const int>
标记进行测试,以防万一),Linux上的g ++会发出典型的25 kajillion-lines模板错误。
顺便说一下,这也在IBM FAQ中详细解释。
理论上,正如@James McNellis所说,编译器不需要在矢量实例化中爆炸(如果它是未定义的行为,任何事情都可能发生 - 包括一切工作正常);但是,在赋值语句中违反了应该产生编译错误的标准。
事实上, -std=c++0x
成员返回operator[]
;那一个必须是vector<const int>::reference
的左值(§23.1¶5表66);由于T
属于T
类型,因此它将是const
左值。所以我们归结为(§7.1.5.1¶5),它定义了试图将const
元素赋值为“格式错误”的代码,这需要编译错误或至少是警告,因为赋值到const
是可诊断的规则(§1.4¶1-2)(没有指定“不需要诊断”语句)。
最终修改
实际上,@ James McNellis是对的;一旦你通过实例化const
调用了未定义的行为,通常的规则就会停止拥有值,所以实现仍然是标准的 - 无论它做什么 - 包括从元素类型中删除vector<const int>
或生成通常的鼻子恶魔。