我们可以依靠减容能力吗?
它实际上保证在任何地方,下面的减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的容器a
和b
,expression式a.swap(b)
应交换a
和b
的值,而不对每个容器元素调用任何移动,复制或交换操作。
这保证了向量的内部指针必须交换。
但是,我找不到任何能够保证新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交换可以得到更好的结果。