我们可以依靠减容能力吗?

它实际上保证在任何地方,下面的减less容量技巧将“工作”?

int main() { std::string s = "lololololol"; s = ""; // capacity still non-zero string(s).swap(s); // ? } 

它似乎并不“为我工作”(因为容量不为零),在标准中我找不到任何东西,除了“内容”必须在两者之间交换之外,相同的]物体。

同样,对于序列容器:

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

据我所知,这个“伎俩”是半被广泛使用的; 也许这种广泛采用被误导了?

(当然,在C ++ 11中,我们使用了shrink_to_fit (尽pipe不是绑定),而是做了这种模拟。)

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

§23.2.1 \ 8说:

对于非array的标准容器types的容器ab ,expression式a.swap(b)应交换ab的值,而不对每个容器元素调用任何移动,复制或交换操作。

这保证了向量的内部指针必须交换。
但是,我找不到任何能够保证新buildvector能力的东西。

§21.4.2 \ 1说basic_string默认构造函数的后置条件之一是capacity()返回一个未指定的值。
§21.4.2 \ 3说basic_string拷贝构造函数的后置条件之一是capacity()返回一个至less和size()一样大的值。
§21.4.6.8 \ 2表示string::swap在常量时间内运行,这实际上要求内部指针交换。

据我所知,符合的实现可以有string::max_size() { return 4;} ,并且交换所有内部从一个缓冲到另一个将因此是恒定的时间。 (虽然vector不能这样做)

显然,这一切都用一粒盐。 我从11月2月28日的C ++草案中引用,我无法find向量拷贝构造函数的规范。 另外,找不到证据与寻求证据不一致

Scott Meyers在他的“Effective STL”的勘误表上写道:

当string实现使用引用计数时, 使用拷贝构造函数的交换技巧不会减less容量,因为拷贝构造函数没有分配任何内存。 只是调整引用计数。 更可靠的方法是通过范围构造函数创build临时string,例如string(s.begin(),s.end())。swap(s); 这个版本的交换技巧对于向量来说也是比较安全的,因为它消除了拷贝构造函数复制另一个向量的多余容量的可能性(允许执行的实现)。

对于“保证”,Meyers指出:

语言警察要求我通知你,这种技术不能保证真正消除多余的能力。 如果愿意,实施者可以自由地提供向量和string的过剩容量,有时他们也想要。 [有效的STL,第17项]

来自http://www.gotw.ca/gotw/054.htm

一些实现可能会select稍稍将容量四舍五入到下一个较大的内部“块大小”,结果容量实际上最终略大于大小。

这是如何工作的,可能完全是实现定义的。 与像vector这样的容器不同,string可以有非常不同的实现。

如果string实现使用小string优化,则不能将容量降低到一定的阈值以下。 如果string实现使用写时复制,则不会发生写入,也不会产生实际的副本。

根据http://www.gotw.ca/gotw/054.htm ,缩小适合和清晰完全是不同的技巧。 如果意图是完全清除,那么用默认构造的string交换可以得到更好的结果。