2015-05-08 20 views
5

Używam XCode, Yosemite.pusty nawias klamrowy {} jako koniec zakresu

Poniższy kod został skompilowany, ale zawiesza się w czasie wykonywania, dlaczego?

Celowo użyłem "{}" w drugim std :: copy jako "koniec zakresu".

Eksperymentowałem z tym kodem z powodu działającego przykładu, który użył "{}" jako "domyślnie skonstruowanego iteratora strumienia jako końca zakresu".

Dlaczego więc ten (patrz drugi kod) działa, ale ten (pierwszy kod) nie działa?

#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)); 

} 

następujący kod jest od drugiej edycji C++ biblioteki standardowej.

Linia z "// koniec źródła" może być albo "istream_iterator()" lub po prostu "{}"

oba działa, ponieważ: cytat z książki

„Należy zauważyć, że od C++ 11 można przekazać puste nawiasy klamrowe zamiast domyślnego iteratora strumienia jako końca zakresu, ponieważ ten typ argumentu definiujący koniec zakresu źródłowego wywodzi się z poprzedniego argumentu, który definiuje początek zakresu źródłowego. "

/* 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 
} 

Odpowiedz

5

Pierwszy powiodła się, ponieważ typ swojej iterator nie jest stream_iterator.

Dla przypadku stream_iterator domyślny konstruktor ma specjalne znaczenie - EOF. Iterator reprezentujący koniec kontenera nie jest domyślnie skonstruowany. (W praktyce dla prostych kontenerów iteratory mogą być po prostu wskaźnikami).

Domyślne iteratory konstrukcyjne inne niż iteratory strumieniowe zwykle nie mają większego sensu i nie mają semantyki, którą chcesz zastosować w tym przypadku.

(Niektóre inne iteratory z doładowania oprócz iteratorów strumieniowych mają taki sam wzorzec, jak robią to iteratory strumieniowe).

+2

masz. {} po prostu oznacza domyślne tworzenie iteratorów; to znaczenie domyślnego konstruktora stream_iterator sprawiło, że jest on wyjątkowy w tym kontekście. Drugi to sztuczka, dobra sztuczka. – milesma

+0

W dzisiejszych czasach iteratory zazwyczaj nie są wskaźnikami, nawet w przypadkach, w których mogą być (wektory i łańcuchy). –

+0

@ T.C. Nawet jeśli nie są wskaźnikami, iteratory wektorowe i łańcuchowe są zwykle cienkimi owijkami wokół wskaźników, przynajmniej w zoptymalizowanych kompilacjach. Podstawowe założenia dla wydajnych iteratorów nie zmieniły się tak bardzo. Np. W przypadku libstdC++ to cienkie opakowanie nazywa się __gnu_cxx :: __ normal_iterator. –

Powiązane problemy