Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.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++ 我们可以依靠减少容量的技巧吗?_C++_Std - Fatal编程技术网

C++ 我们可以依靠减少容量的技巧吗?

C++ 我们可以依靠减少容量的技巧吗?,c++,std,C++,Std,在任何地方都可以保证以下减少容量的技巧“有效”吗 它似乎对我来说“不起作用”(容量保持为非零),我在标准中找不到比“内容”必须在两个(这里是相同的)对象之间交换更重要的内容 同样,对于序列容器: int main() { vector<int> v { 1,2,3,4,5 }; v.clear(); // capacity still non-zero vector<int>(v).swap(v); //

在任何地方都可以保证以下减少容量的技巧“有效”吗

它似乎对我来说“不起作用”(容量保持为非零),我在标准中找不到比“内容”必须在两个(这里是相同的)对象之间交换更重要的内容

同样,对于序列容器:

int main() {
   vector<int> v { 1,2,3,4,5 };
   v.clear();                   // capacity still non-zero

   vector<int>(v).swap(v);      // ?
}
intmain(){
向量v{1,2,3,4,5};
v、 clear();//容量仍然非零
向量(v)。交换(v);/?
}
据我所知,这种“把戏”被半广泛使用;也许这种广泛采用是错误的

(当然,在C++11中,我们使用了
收缩以适应
[尽管不具有约束力]来代替这种模拟。)

来自:

一些实现可能会选择稍微提高容量以 他们的下一个更大的内部“块大小”,其结果是 实际上,容量最终略大于大小


我一直被教导,没有保证标准的方法来降低容量。所有方法都已经(现在仍然)定义了实现

§23.2.1\8规定:

用于标准容器
a
b
的表达式
a.swap(b)
数组
以外的容器类型应交换
a
b
无需对单个服务器调用任何移动、复制或交换操作 容器元素

这保证了向量的内部指针必须交换。
然而,我找不到任何能保证新创建的向量容量的东西

§21.4.2\1说明
基本字符串
默认构造函数的post条件之一是
容量()
返回未指定的值。
§21.4.2\3说字符串复制构造函数的基本post条件之一是
capacity()
返回的值至少与
size()一样大

§21.4.6.8\2规定
string::swap
以恒定时间运行,这(有效地)要求交换内部指针

据我所知,一致性实现可以具有
string::max_size(){return 4;}
,因此,将所有内部构件从一个缓冲区交换到另一个缓冲区将是一个恒定的时间。(不过vector不能这么做)


显然,这一切都是一厢情愿的。我引用了FEB28,11的C++草稿,我找不到矢量复制构造函数的规范。此外,不为找到证据与为找到证据不一样。

这一工作原理可能完全由实现定义。与vector等容器不同,字符串可以有非常不同的实现

如果字符串实现使用小字符串优化,那么不能将容量降低到某个阈值以上。如果字符串实现使用写时复制,则不会发生写操作,也不会进行真正的复制

据了解,收缩到适合和完全清除是不同的技巧。如果目的是完全清除,那么使用默认构造的字符串进行交换可以获得更好的结果。

斯科特·迈尔斯在他的“有效STL”中指出:

当字符串实现使用引用计数时,交换技巧 使用复制构造函数不会降低容量,因为 复制构造函数没有分配任何内存;这只是调整一个 参考计数。更可靠的收缩至配合方法是 通过范围构造函数创建临时字符串,例如。, 字符串(s.begin()、s.end()).swap;这个版本的交换技巧是 对于向量也更安全,因为它消除了复制 构造函数将复制另一个向量的多余容量(这 实现是允许的)

至于“担保”,迈尔斯指出:

语言警察要求我通知你没有 保证这项技术将真正消除过剩产能。 如果需要,实现者可以自由地提供向量和字符串多余的容量 他们想,有时他们也想。[生效的STL,项目17]


您可能正在研究小字符串优化。当您说“容量保持非零”时,报告的容量是多少?哦,当然这不适用于矢量,矢量是你的精确代码,你是在用字符串本身交换字符串。@UncleBens:他在构造一个临时字符串并用它交换。(其想法是复制构造函数将分配最少的内容。)我怀疑GCC的字符串是写时复制的,因此实现意识到您并不是在真正复制,因此容量不会以这种方式减少。请参阅@UncleBens:
string().swap
会导致
s
变为空,这显然不是目的。如果你能在标准中找到支持这些单词的位置,那就太好了。我不能,所以问题来了!嗯。。。呼叫萨特博士。。。分页Sutter博士(Herb Sutter不够标准吗?-哦,好吧)我想关键是
swap()
是否真的像Herb所说的那样交换了内部构件,这样结果就具有了临时而不是原始容器的容量。但这句话涉及的是与默认容器的交换,而不是其自身的副本。关于后者的评论是:“(一些实现可能会选择将容量稍微四舍五入到下一个更大的内部“块大小”,其结果是容量实际上最终略大于大小。)”好的,是的,但显然这里的块大小与此无关()-13(或14)几乎不是块大小。哈哈,“语言警察”。迈尔斯承认“可靠”一词完全是胡说八道的可笑方式。
int main() {
   vector<int> v { 1,2,3,4,5 };
   v.clear();                   // capacity still non-zero

   vector<int>(v).swap(v);      // ?
}