标准库/模板化容器的常量语义的经验法则
Rule-of-thumb for const semantics for standard library/templated containers?
>当有人写了
template <typename T> class Container;
当你有一个const Container<const MyType>
时会发生什么就很清楚了(好吧,假设你知道常量对MyType
意味着什么(。你不能改变任何东西 - 没有重新排序结构,没有添加或删除元素,不能改变现有元素;如果引擎盖下确实发生了变化(例如 mutable
(你应该另眼相看,因为它不算数。
你所说的Container<MyType>
是什么意思也很清楚 - 一切都是可变的(可变类中的常量成员除外等(
当你将恒常性与非恒常性混合在一起时,事情就会变得混乱。有了const Container<MyType>
- 期望修改MyType
元素是否合理?如果容器的状态取决于它们的值怎么办?另外,如果我有
using Stuff = Container<MyType>;
然后我传递const Stuff
参数。这种不透明的措辞让你质疑你是否"应该"改变 Stuff 元素中的任何内容;毕竟,你不能说"深const
Stuff
,不要碰里面的任何东西"。没有人喜欢写作:
using ConstStuff = Container<const MyType>;
然后把尴尬的const ConstStuff
传来传去。然而,标准容器完全(?(能够为自己生活const
,但不能为他们的元素生活。
甚至Container<const MyType>
的语义也会带来一定的语义问题:您可以删除容器中的项目;并且可能需要能够复制它们。这并不能构成非常const
的 y 元素。
最后,当您有多个模板化类型参数时,事情会变得更加混乱。假设现在是
template <typename K, typename V> class Container;
(是的,这就像一个std::map
,这是这个问题的动机。有了这个,你可以拥有一个恒定的容器但可变的键 - 荒谬,对吧?你可以通过改变它们来完全搞砸它。或者,假设它是一个具有const
键但非const
值的容器,并假设它通过不保留相同值的多个副本而是指向该值的单个副本来最小化存储。然后你来改变这个值。
在这些情况下,关于 const 的语义是否有某种约定或经验法则?
注意:我特别忽略了指针,您也可以在答案中忽略它们(如果您愿意,也可以忽略它们(。
更适合 programmers.stackexchange.com,但没关系。
如果引擎盖下确实发生了变化(例如可变(,您应该另辟蹊径,因为它不算数。
不,有些事情可能会合法地改变。 因为这个const Container
可能只是一个你特别不能修改的接口,而实现它的人可能为自己保留了随意修改它的自由,这完全没问题。 将这const Container
交给您的人可能这样做是为了不必实例化新容器,也不必制作自己的非常量容器内容的安全副本。
当你将恒常性与非恒常性混合在一起时,事情就会变得混乱。使用 const 容器 - 期望修改 MyType 元素是否合理?
是的。 这就是为什么它是const Container<MyType>
而不是const Container<const MyType>
. 完全合理。
如果容器的状态取决于它们的值怎么办?
好吧,那时事情会变得混乱。但这真的很奇怪。 (这就是非常奇怪的事情通常发生的事情:它们开始变得混乱。
甚至 Container 的语义也会带来一定的语义问题:您可以删除容器中的项目;并且您可能需要能够复制它们。这并不能构成非常温和的元素。
不,这些元素是完全 consty 的,因为通过从 const 对象复制来初始化实例正是复制构造函数所做的,并且因为从容器中删除对象并不意味着需要对对象执行任何操作,即使对象由于从容器中删除而被破坏, 调用 const 对象的析构函数是完全可以的。
最后,当您有多个模板化类型参数时,事情会变得更加混乱。假设现在它是
template <typename K, typename V> class Container;
(是的,它就像一个std::map,这是这个问题的动机。有了这个,你可以拥有一个恒定的容器但可变的键 - 荒谬,对吧?
是的,那有点荒谬。 但是语言必须为您提供声明具有不可变键和可变值的容器的能力,因此该语言必须提供完成此类操作所需的功能。
除了密切关注恒常性之外,我不知道该提出什么建议。
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 什么时候在C++中返回常量引用是个好主意
- 代理对象的常量正确性
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 何时在引用或唯一指针上使用移动语义
- 通过多个头文件使用常量变量
- 在cuda线程之间共享大量常量数据
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 如何从具有移动语义的类对象中生成共享指针
- 是默认情况下分配给char数组常量的值
- Boost Spirit,获取迭代器内部语义动作
- 如何避免语法相同的常量和非常量函数之间代码重复,这些函数在语义上不相同
- 传递指向常量指针的指针到字节数组的语义冲突
- 移动语义和常量引用
- C++中的常量正确性语义
- 标准库/模板化容器的常量语义的经验法则
- 将值赋给常量的语法或语义错误
- C++11编译器何时会使RVO和NRVO优于移动语义和常量引用绑定