空花括号 {} 作为范围的结尾

6

我正在运行XCode Yosemite。

下面的代码编译通过,但在运行时崩溃了,为什么?

我故意在第二个std::copy中使用“{}”作为“范围结束”。

我尝试了这段代码,是因为有一个可行的示例使用“{}”作为“默认构造的流迭代器作为范围结束”。

那么为什么第二个代码可以工作,而第一个代码失败了?

#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
    vector<int> coll1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    // copy the elements of coll1 into coll2 by appending them
    vector<int> coll2;
    copy (coll1.cbegin(), coll1.cend(),    // source
          back_inserter(coll2));           // destination

    vector<int> coll3;
    copy (coll1.begin(), {},
          back_inserter(coll3));

}

以下代码来自《C++标准库第二版》。
带有“// end of source”的那一行可以是“istream_iterator()”,也可以是“{}”,两者都可以,因为:引用自该书的话,“请注意,自C++11起,您可以传递空花括号作为范围结束的默认构造流迭代器。这是可行的,因为定义源范围结束的参数的类型是从定义源范围开始的前一个参数推导出来的。”
/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
 * by Nicolai M. Josuttis, Addison-Wesley, 2012
 *
 * (C) Copyright Nicolai M. Josuttis 2012.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
#include <iterator>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    vector<string> coll;

    // read all words from the standard input
    // - source: all strings until end-of-file (or error)
    // - destination: coll (inserting)
    copy (istream_iterator<string>(cin),    // start of source
          {},       // end of source
          back_inserter(coll));             // destination

    // sort elements
    sort (coll.begin(), coll.end());

    // print all elements without duplicates
    // - source: coll
    // - destination: standard output (with newline between elements)
    unique_copy (coll.cbegin(), coll.cend(),           // source
                 ostream_iterator<string>(cout,"\n")); // destination
}
1个回答

6
第一个翻译失败是因为您的迭代器类型不是 stream_iterator
对于 stream_iterator,默认构造函数具有特殊含义 - EOF。表示容器结束的迭代器不是默认构造的。(实际上,对于简单的容器,迭代器可以只是指针)。
除了流迭代器之外,通常没有必要默认构造其他迭代器,并且在这种情况下也不具备所需的语义。
(除 stream 迭代器外,boost 中的其他一些迭代器遵循与其相同的模式)。

2
明白了。{} 只是默认构造迭代器;而 stream_iterator 的默认构造函数在这种情况下具有特殊意义。因此第二个是一个技巧,一个好的技巧。 - milesma
现在,即使在可以使用指针的情况下(如向量和字符串),迭代器通常也不是指针。 - T.C.
1
即使它们不是指针,向量和字符串迭代器在优化构建中通常是指针的薄包装。高效迭代器的基本假设并没有发生太大变化。例如,在libstdc++中,这个薄包装被称为__gnu_cxx::__normal_iterator。 - Arne Vogel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接