Jeśli elementy w std::initializer_list
są zawsze wartościami stałymi, dlaczego mamy metodę szablonową, taką jak begin()/end()
, a nie cbegin()/cend()
? Te nazwy (według konwencji, na przykład w porównaniu z np. std::vector
) mogą sugerować, że zarówno metoda std::initializer_list
może zwrócić iterator
, kiedy zawsze zwracają const_iterator
.std :: initializer_list bez cbegin()/cend()
Odpowiedz
Chociaż nie może zapewnić wgląd w przyczyny dlaczego cbegin()
i cend()
nie są częścią interfejsu std::initializer_list
„s opróczbegin()
i end()
, są z pewnością dobre powody, dla których dwie ostatnie funkcje składowe powinny być tam.
Jednym powodem jest to, na przykład, że zasięg oparte for
pętla jest zdefiniowana przez standard C++ 11 dokładnie pod względem funkcji begin()
i end()
(§ 6.5.4/1). Dlatego też, w celu umożliwienia używać go z listy initializer, std::initializer_list
musi dostarczyć begin()
i end()
członków funkcje:
#include <utility>
#include <iostream>
int main()
{
auto l = { 1, 2, 3, 4, 5 };
for (int x : l) // Works because std::initializer_list provides
// the member functions begin() and end().
{
std::cout << x << " ";
}
}
Ponadto, warto wziąć pod uwagę, że funkcje składowe cbegin()
i cend()
nie były obecne przed C++ 11: dlatego posiadanie begin()
i na interfejsie std::initializer_list
pozwala na to, aby stare standardowe algorytmy napisane pod kątem begin()
i end()
działały również z listami inicjalizującymi, bez konieczności ich przepisywania.
Piszesz:
Nazwy te (konwencje, w porównaniu do np
std::vector
) może sugerować, że zarówno metodastd::initializer_list
iterator
mógł wrócić, kiedy zawsze wrócićconst_iterator
.
W rzeczywistości ta analogia nie jest odpowiednia. Funkcja std::vector
jest begin()
przykładowo zwraca iterator
po uruchomieniu na non const
wystąpienia std::vector
(czyli zmienny jednym, którego elementy mogą być modyfikowane, dodane lub usunięte) i const_iterator
po uruchomieniu na przykład const
(tj. niezmienny, którego zawartość nie może być zmieniona):
#include <vector>
#include <type_traits>
int main()
{
// A non-const vector...
std::vector<int> v = { 1, 2, 3, 4, 5 };
auto i = v.begin();
static_assert(
std::is_same<decltype(i), decltype(v)::iterator>::value,
// ^^^^^^^^
// ...non-const iterator!
"What?");
// A const vector...
std::vector<int> const vc = { 1, 2, 3, 4, 5 };
auto ic = vc.begin();
static_assert(
std::is_same<decltype(ic), decltype(vc)::const_iterator>::value,
// ^^^^^^^^^^^^^^
// ...const iterator!
"What?");
}
Listy inicjalizujące są z definicji kolekcjami niezmiennymi. Na § 18,9/2 C++ 11 Standard:
obiektu typu
initializer_list<E>
zapewnia dostęp do tablicy obiektów typuconst E
. [...]
Ponieważ list initializer są zbiory const
elementów, gdy cbegin()
i cend()
funkcje faktycznie robić dokładnie to samo, że begin()
i end()
zrobić.
W rzeczywistości iterator
i const_iterator
są zarówno zdefiniowane jako wskaźniki do stałych elementów listy initializer typ wartości, więc spierać czy jest to przypadek, że begin()
i end()
zawsze powrócić const_iterator
(jak zakładam), czy też zawsze return iterator
.
To jest jak Paragraf 18.9/1 o C++ 11 standard definiuje szablon initializer_list
Klasa:
namespace std {
template<class E> class initializer_list {
public:
typedef E value_type;
// ...
typedef const E* iterator;
typedef const E* const_iterator;
// ...
constexpr const E* begin() const noexcept; // first element
constexpr const E* end() const noexcept; // one past the last element
};
// ...
}
Pamiętam, kiedy przyzwyczaiłem się do otrzymania repa na SO, ale wtedy pojawiła się osoba, która odpowiedziała na wszystkie dobre pytania w C++ w doskonałej formie . Teraz mogę tylko głosować. +1 – GManNickG
@GManNickG: Jestem pochlebiony i chociaż wierzę, że komplementujesz mnie bardziej, niż na to zasługuję, bardzo się cieszę, że otrzymałem twoje wsparcie. Dziękuję Ci. –
@GManNickG: Pomyśl o wszystkich ludziach z C#, którzy byli Jonami od pierwszego dnia. – MSalters
- 1. std :: make_shared z std :: initializer_list
- 2. std :: initializer_list dedukcja typu
- 3. Alias std :: initializer_list w brzękiem
- 4. uszkodzenie pamięci z std :: initializer_list
- 5. Wracając std :: initializer_list w brzękiem
- 6. powrót i auto wywieść std :: initializer_list
- 7. Jaka jest podstawowa struktura std :: initializer_list?
- 8. Sprawdzanie poprawności zawartości std :: initializer_list podczas kompilacji
- 9. std :: initializer_list dwuznaczność w Visual Studio
- 10. Dlaczego rozmiar nie jest szablonem argumentu std :: initializer_list?
- 11. Konwersja zmiennej liczbie argumentów szablonu pakiet do std :: initializer_list
- 12. Jak korzystać initializer_list
- 13. Jak przenieść elementy pliku initializer_list?
- 14. Wywołanie konstruktora initializer_list przez make_unique/make_shared
- 15. Rozszerzenie parametru pakiet zawierający initializer_list konstruktorowi
- 16. Dlaczego auto x {3} dedukuje listę initializer_list?
- 17. Czy można zadeklarować obiekt constexpr initializer_list?
- 18. initializer_list nie pracuje w VC10
- 19. Czy puste nawiasy wywołują domyślny konstruktor lub konstruktor pobierający std :: initializer_list?
- 20. Jaka jest różnica między std :: initializer_list <int> ({1,2,3}) i {1,2,3}?
- 21. Jak uzyskać długość std :: stringstream bez kopiowania
- 22. initialize std :: array bez kopiowania/przenoszenia elementów
- 23. Strumień ze std :: string bez tworzenia kopii?
- 24. std :: enable_if Z parametrami szablonu bez szablonu
- 25. Zwracanie C++ std :: wektor bez kopii?
- 26. Uzyskaj rozmiar std :: tablicę bez instancji
- 27. Nie można skopiować std :: wektor <std :: function <void()>> za pomocą jednolitej inicjalizacji. Czy to jest poprawne?
- 28. Inicjalizacja std :: tuple z listy inicjalizatora
- 29. Dlaczego podwójne puste nawiasy klamrowe {{}} tworzą std :: initializer_list <double> z jednym elementem, a nie zerem?
- 30. Do czego służy funkcja std :: ref w tej funkcji?
dobre pytanie. Dobra robota. –
@LightnessRacesinOrbit Hej piękna, miło cię poznać tutaj :-) – Des1gnWizard
@ Des1gnWizard: To nie jest serwis randkowy, dziękuję. –