Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 标准库/模板化容器的const语义的经验法则?_C++_Templates_Stl_Constants_Container Data Type - Fatal编程技术网

C++ 标准库/模板化容器的const语义的经验法则?

C++ 标准库/模板化容器的const语义的经验法则?,c++,templates,stl,constants,container-data-type,C++,Templates,Stl,Constants,Container Data Type,当有人写了一篇文章 template <typename T> class Container; 然后我传递const Stuff参数。这种含糊不清的措辞让你怀疑你是否“应该”改变事物元素中的任何东西;毕竟,你不能在Stuff上说“deepconst,也不能碰里面的任何东西”。没有人喜欢写作: using ConstStuff = Container<const MyType>; 使用ConstStuff=Container; 然后将笨拙的const constuf

当有人写了一篇文章

template <typename T> class Container;
然后我传递
const Stuff
参数。这种含糊不清的措辞让你怀疑你是否“应该”改变事物元素中的任何东西;毕竟,你不能在
Stuff
上说“deep
const
,也不能碰里面的任何东西”。没有人喜欢写作:

using ConstStuff = Container<const MyType>;
使用ConstStuff=Container;
然后将笨拙的
const constuff
传递给周围的人。然而,std容器完全(?)能够为其自身而不是为其元素使用
const
ness

即使是
容器的语义
也会造成一定的语义问题:您可以删除容器中的项目;你可能需要能够复制它们。这不适用于非常
const
y元素

最后,当您有多个模板化类型参数时,事情会变得更加混乱。假设现在是

模板类容器

(是的,它就像一个
std::map
,这是这个问题的动机。)有了它,你可以有一个恒定的容器,但可以有可变的键-荒谬,对吗?你可以通过变异它们把事情搞砸。或者,假设它是一个包含
const
键但不包含
const
值的容器,并假设它通过不保留相同值的多个副本而指向该值的单个副本来最小化存储。然后你来改变这个值

在这些情况下,const的语义是否有某种约定或经验法则

注意:我特别忽略了指针,您也可以在回答中忽略它们(或者不忽略,如果您愿意)。

这个问题更适合程序员。stackexchange.com,但没关系

如果引擎盖下的某些东西发生了变化(例如可变),你应该换个角度看,因为它不算数

不,某些事情可能会合法地改变。因为这个
const容器
可能只是一个接口,您无法修改它,而实现它的任何人都可能为自己保留了随意修改它的自由,这是非常好的。无论是谁递给你这个
const容器
,都可能是为了不必实例化一个新容器,也不必制作自己的非const容器内容的安全副本

当你把恒定和非恒定混为一谈时,事情就会变得混乱。使用const Container-期望修改MyType元素是否合理

嗯,是的。这就是为什么它是
const-Container
,而不是
const-Container
。完全合理

如果容器的状态取决于它们的值怎么办

好吧,那时候事情会变得混乱。但那真的很奇怪。(这是非常奇怪的事情通常发生的情况:它们开始变得混乱。)

即使是容器的语义也会造成一定的语义问题:您可以删除容器中的项目;你可能需要能够复制它们。这并不构成非常稳定的因素

不,元素是完全常量的,因为复制构造函数正是通过从常量对象复制来初始化实例的,而且从容器中移除对象并不意味着需要对对象执行任何操作,即使对象由于从容器中移除而被破坏,调用const对象的析构函数也是完全正确的

最后,当您有多个模板化类型参数时,事情会变得更加混乱。假设现在它是
模板类容器(是的,它就像一个std::map,这是这个问题的动机。)有了它,你可以有一个恒定的容器,但可以有可变的键-荒谬,对吗

是的,那有点可笑。但是,该语言必须为您提供声明具有不可变键和可变值的容器的能力,因此该语言必须提供实现这一点所必需的功能


除了密切关注constness之外,我不知道该建议什么。

至少就个人而言,我认为常量容器不应该让任何人修改元素。想象一个函数通过常量引用获取一个容器:@JamesRoot:我希望容器在函数末尾是相同的,而不是用不同的东西替换每个值,那么它不应该让非常量元素的编译失败吗?另外,MikeNakis似乎有不同的想法…@JamesRoot如果const容器是一个具体的类,当然没有人会期望它的内容会改变。但如果它是一个接口(全部是纯虚拟方法,没有实现),那么就不能保证它的内容不会改变。这是生活中的事实。不变性是实现的属性,而不是接口的属性。关于接口,您最多只能说它是不可修改的。但是-您不知道容器的状态是否取决于其值。这可能会被封装在你身边——或者你的代码只是通过一个模板使用一个概念(例如,插入、删除、开始/结束等等)。具体来说,有序结构就是这样的,它们并不深奥。所以,这可能并不荒谬。也许std::map的作者允许使用非常量键或非常量值,并为这些情况提供了不同的实现(这并不是说它是一个超级高效的实现,但没关系)。更重要的是,标准库容器如何处理这些看似荒谬的情况可能有一个惯例。另一点:您是否认为
std::map
s应该始终具有const键类型?嗯,
const
键意味着map承诺不会更改它们
using ConstStuff = Container<const MyType>;