我们能依靠容量缩减技巧吗
Can we rely on the reduce-capacity trick?
是否在任何地方都能保证下面的减少容量技巧将"工作"?
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
[尽管不是绑定的]来代替,这就没有意义了)
我一直被告知,没有保证的标准方法来降低容量。所有的方法都已经(现在仍然)定义了实现。
§23.2.18说:
表达式
a.swap(b)
,表示标准容器a
和b
除array
以外的容器类型,应交换a
和b
的值不调用任何移动、复制或交换操作容器元素…
这保证了必须交换vector的内部指针。
但是,我找不到任何保证新创建的vector的容量的方法。
§21.4.21说basic_string
默认构造函数的post条件之一是capacity()
返回一个未指定的值。
§21.4.23说basic_string复制构造函数的post条件之一是capacity()
返回的值至少和size()
一样大。
§21.4.6.82说string::swap
在常量时间内运行,这(有效地)需要交换内部指针。
据我所知,一个符合string::max_size() { return 4;}
的实现,从一个缓冲区交换到另一个缓冲区的所有内部将是常数时间。(vector不能这么做)
显然,对这一切持保留态度。我引用的是2011年2月28日的c++草案,我找不到vector的复制构造函数的规范。此外,没有找到支持的证据与找到反对的证据是不一样的。
在他的"Effective STL "的勘误表页面上,Scott Meyers写道:
当字符串实现使用引用计数时,使用交换技巧使用复制构造函数不会减少容量,因为复制构造函数没有分配任何内存;它只是调整了a引用计数。一个更可靠的执行收缩适应的方法是通过range构造函数创建临时字符串,例如:字符串(s.begin (), s.end ()) .swap(年代);这个版本的交换技巧是对向量也更安全,因为它消除了复制构造函数将复制另一个vector的剩余容量(其中
至于"保证",Meyers指出:
语言警察要求我告诉你没有保证此技术将真正消除过剩容量。实现者可以自由地为向量和字符串提供多余的容量他们想这么做,有时他们也想这么做。[生效STL,第17条]
从http://www.gotw.ca/gotw/054.htm:
一些实现可能会选择将容量稍微四舍五入到它们的下一个更大的内部"块大小",结果是容量实际上最终比大小稍大。
如何工作可能完全是由实现定义的。与vector等容器不同,字符串可以有非常不同的实现。
如果字符串实现使用小字符串优化,那么您不能将容量降低到某个阈值以上。如果字符串实现使用写时复制,则不会发生写操作,也不会进行真正的复制。
根据http://www.gotw.ca/gotw/054.htm,收缩到适合和完全清除是不同的技巧。如果目的是完全清除,那么使用默认构造的字符串交换可以获得更好的结果。
- 具有非整数边容量的最大流量的Dinic算法
- 将stl字符串缩小到小于15个字符的容量
- 在容量内调整矢量大小时的性能影响
- std::vector的容量会降低吗?
- 可视化C++载体:未使用的容量
- 如何在 c++ 中清除矢量容量?
- 当我将其插入无序地图时,矢量的容量为 0
- OLE DB 大容量复制操作始终将 true 加载到位列中
- 将结构 std::memcpy 转换为具有足够容量的 std::vector 是未定义的行为<char>吗?
- std::string::reserve没有被允许创建具有精确容量的std::string
- 当矢量改变容量时,有什么方法可以更新指针/参考值
- 使用准备好的语句大容量插入到postgresql
- 制作 std::矢量容量>=N 和大小=0 的最佳方法是什么?
- C++ STL 向量保留太多容量会消耗大量内存吗?
- 为 STD 载体模板专业化预留容量<bool>
- 英特尔 TBB 计算图:如何指定节点的输入队列容量
- 在 Linux 中禁用 USB 大容量存储设备的读取缓冲
- 在具有容量/调整大小的类中初始化向量
- 我可以依靠 initializer_list::const_iterator 是一个普通的指针吗?
- 我们能依靠容量缩减技巧吗