为什么basic_string :: append(iter,iter)不调用std :: copy?

时间:2012-11-26 22:30:47

标签: c++ string copy

我刚才发现,在Visual Studio C ++ 2010中,basic_string::append (iter, iter)显然没有使用std::copy来实现。

第一个问题:

现在假设我实现了自己的迭代器类型,并为我的迭代器类型优化了std::copy的重载,以便提供更有效的逐块复制。除了重载basic_string::append之外,还有什么方法可以让append使用此优化吗?

basic_string::append (iter, iter)是否有可能不进行字符复制?

第二个问题(作为我自己实施的起点):

以下是否保证有效?

std::string t ("JohnB");
std::string s;
s.reserve (10);
std::copy (t.begin (), t.end (), s.begin ());
s.push_back ('\0');

或者我应该更好地使用back_inserter?如果我使用back_inserter - 我怎么能避免按字符复制?

2 个答案:

答案 0 :(得分:5)

字符串类有自己的traits类,它定义了它可以对它包含的字符执行的操作。

要复制charbasic_string<char>将使用std::char_traits<char>::copy(而不是更一般的std::copy)。这可能映射到标准C库中的memcpy函数。

答案 1 :(得分:2)

std::basic_string<cT, ...>::append()的定义在最终到达重载之前保持委派一些时间(21.4.6.2 [string :: append]第7段):

  

basic_string& append(const charT* s, size_type n);

此时显然没有剩下原始迭代器。如果您想知道输入迭代器会发生什么变化,您可能已经传递给append(),同一段落的第17段中的重载将其删除,其中指出:

  

效果:相当于append(basic_string(first, last))

处于某种中间状态。如果按照标准的字面说明方式实施标准库,则显然没有调用std::copy()

但是,无论如何,你真的无法看到std::copy()的重载版本。

的道德等同于图书馆可能做的事情
template <typename InIt>
std::basic_string<cT, ...>& std::basic_string<cT, ...>::append(InIt begin, InIt end) {
    if (is_forward_iterator<begin>::value) {
        this->reserve(this->size() + std::distance(begin, end));
    }
    std::copy(begin, end, back_inserter_without_capacity_check<InIt>(*this);
}

现在,另一个有趣的是:即使这是它实现的方式,它对std::copy()也没有真正帮助你!你不能部分地专门化std::copy()(好吧,你不能部分地专门化任何函数模板)并且没有定义目标迭代器的类型(在上面的实现中它将是{{1}的非容量检查变体如果std::back_inserter()是前向迭代器,则它只与InIt相同。