繁体   English   中英

const_cast const STL容器,它是未定义的行为吗?

[英]const_cast const STL container, is it undefined behavior?

我知道使用const_cast不会引入未定义的行为(即可以安全使用),只要您要const_cast ing的变量最初未定义为const或如果最初定义为const而不是通过其const_cast ed别名对其进行修改。

但是,众所周知,大多数STL容器(例如std::vectorstd::set )都是动态分配其内部缓冲区的。 基于这个事实,我认为将const定义的std::vector放置在只读内存中是不可能的。

自然地,如果上述情况成立,我就假设即使将STL容器定义为const ,例如:

std::vector<int> const v;

const_cast并通过其const_cast ed别名对其进行更改是合法的,不会引起任何未定义的行为。

以上假设成立还是我错了?

C ++标准明确指出,将通过new const T创建的对象抛弃const并对其进行修改是未定义行为。

例如,C ++ 11标准在其§7.1.6.1/ 4中包含以下示例:

 const int* ciq = new const int (3); // initialized as required int* iq = const_cast<int*>(ciq); // cast required *iq = 4; // undefined: modifies a const object 

标准中的示例是非规范性的,仅是示例,可能是错误的。 例如,在C ++ 03中,几乎所有使用<iostream>示例都是错误的(当时正式需要同时包含<ostream> ,但这并不是委员会的意图),而C语言中的表达式示例++ 03§5/ 4是错误的,表示该行为是未指定的,而不是未定义的(这可能反映了最初的意图)。 但是,以上示例是正确的。

这表明动态分配的内存不必是可变的:对其进行修改可以具有未定义的行为。

但是,当创建例如std::string ,其对缓冲区(如果有)的分配发生在构造函数执行期间,此时该对象还不是const ,并且该缓冲区未分配为const 因此,如果分配了缓冲区,则缓冲区最初不是const 但是对于这个特定的示例, std::string可以使用小型缓冲区优化,在这种情况下,它直接在对象中使用存储,然后该对象将最初为const (可能在只读内存中分配)。 而这个去理性的, 没有原来的规则const对象可以被修改。


除了只读内存方案外,UB的基本原理还包括可以为编译器提供优化的可能性。

正如juanchopanza对问题的评论中指出的那样,

优化程序使用此方法来做各种疯狂的事情,这些事情假设const对象不会被修改。

通过修改原始const对象来破坏优化程序的假设,可能会带来灾难性的后果,并且实际上是不可预测的后果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM