首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么SGI STL不使用复制和交换成语?

为什么SGI STL不使用复制和交换成语?
EN

Stack Overflow用户
提问于 2015-05-22 13:19:36
回答 5查看 251关注 0票数 6

我最近在StackOverflow上读到一个关于什么是复制和交换成语?的答案,并且知道复制和交换成语可以。

避免代码重复,并提供强大的异常保证。

然而,当我查看STL deque 实现时,我发现它没有使用这个成语。我想知道为什么不,如果成语某种程度上是一种“最佳实践”?

代码语言:javascript
复制
  deque& operator= (const deque& __x) {
    const size_type __len = size();
    if (&__x != this) {
      if (__len >= __x.size())
        erase(copy(__x.begin(), __x.end(), _M_start), _M_finish);
      else {
        const_iterator __mid = __x.begin() + difference_type(__len);
        copy(__x.begin(), __mid, _M_start);
        insert(_M_finish, __mid, __x.end());
      }
    }
    return *this;
  }       
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-05-22 13:24:16

除非容器需要增长,否则您显示的代码不会重新分配内存,这可能是一个很大的节省。复制和交换总是分配内存来执行复制,然后释放现有元素的内存。

考虑一个deque<vector<int>>,它的现有向量成员具有很大的容量。

代码语言:javascript
复制
deque<vector<int>> d(2);
d[0].reserve(100);
d[1].reserve(100);

使用SGI STL实现,分配给每个元素可以保持该容量,因此,如果向量需要增长,它们可以这样做,而无需分配任何内容:

代码语言:javascript
复制
d = deque<vector<int>>(2);
assert(d[0].capacity() >= 100);
assert(d[1].capacity() >= 100);
d[0].push_back(42);  // does not cause an allocation

复制和交换将用没有空闲容量的新元素替换现有成员,因此上述断言将失败,push_back将需要分配内存。这浪费了时间分配和重新分配,而不是使用已经存在的非常好的内存。

复制和交换是一种非常容易获得异常安全性和正确性的方便方法,但不一定尽可能高效。在像STL或C++标准库这样的代码中,您不希望为了稍微简单的实现而牺牲效率,这样的代码通常应该由能够获得异常安全的专家编写--通过使用“艰难的方法”,而不仅仅是最方便的方法。

票数 8
EN

Stack Overflow用户

发布于 2015-05-22 13:27:03

这个成语是一个简单的方法来提供一个强有力的例外保证,所以它是一个“最佳实践”的意义上做一件好事,除非你有充分的理由不这样做。

然而,这是有代价的:必须创建和销毁第二个对象。这可能是昂贵的,如果这涉及到一个大内存分配,可以增加更多的峰值内存使用是必要的。如果这是一个问题,或者如果您正在编写类似于此的泛型库,那么您应该找到其他方法来复制该对象,而无需创建临时对象。与使用简单的成语相比,异常安全需要更多的注意。

票数 4
EN

Stack Overflow用户

发布于 2015-05-22 13:23:45

虽然复制和交换是最佳实践,但在某些情况下可能会带来效率损失。在这种特殊情况下,代码利用这样一个事实:如果分配给的向量已经有足够的内存可用,则可以复制这些值,而无需进行额外的内存分配。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30397807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档