Uwagi na temat C ++: Inicjalizacja macierzy ma ładną listę nad inicjowaniem macierzy. mam
int array[100] = {-1};
spodziewając się, że będzie pełny z -1, ale nie, tylko pierwsza wartość jest, a reszta to 0 pomieszane z losowymi wartościami.
Kod
int array[100] = {0};
działa dobrze i ustawia każdy element na 0.
Czego tu brakuje? Nie można go zainicjować, jeśli wartość nie jest równa zero?
I 2: Czy domyślna inicjalizacja (jak wyżej) jest szybsza niż zwykła pętla przez całą tablicę i przypisuje wartość, czy robi to samo?
{0}
nie jest specjalnym przypadkiem dla struktur ani tablic. Zasadą jest, że elementy bez inicjalizatora są inicjowane tak, jakby miały0
dla inicjatora. Jeśli istnieją zagnieżdżone agregaty (np.struct x array[100]
), Wówczas inicjatory są stosowane do nieagregatów w kolejności „major-row”; nawiasy klamrowe można opcjonalnie pominąć.struct x array[100] = { 0 }
jest ważny w C; i ważne w C ++, o ile pierwszy członekstruct X
przyjmuje0
jako inicjator.{ 0 }
nie jest czymś specjalnym w C, ale o wiele trudniej jest zdefiniować typ danych, którego nie można zainicjować, ponieważ nie ma konstruktorów, a tym samym nie można powstrzymać się0
przed niejawną konwersją i przypisaniem do czegoś .Odpowiedzi:
Używając użytej składni,
mówi „ustaw pierwszy element na,
-1
a resztę na0
”, ponieważ wszystkie pominięte elementy są ustawione na0
.W C ++, aby ustawić je wszystkie
-1
, możesz użyć czegoś takiego jakstd::fill_n
(z<algorithm>
):W przenośnym C musisz rozwinąć własną pętlę. Istnieją rozszerzenia kompilatora lub możesz polegać na zachowaniu zdefiniowanym jako implementacja jako skrót, jeśli jest to dopuszczalne.
źródło
#include <algorithm>
jest właściwym nagłówkiem,<vector>
może, ale nie musi, zawierać go pośrednio, zależnie od twojej implementacji.int
s i rozwinięcia jej do inicjalizatora tablicy.fill_n
do wypełnienia całej tablicy 2D. Musisz zapętlić jeden wymiar, wypełniając drugi.std::fill_n
nie jest inicjalizacją.Istnieje rozszerzenie kompilatora gcc, które umożliwia składnię:
Spowodowałoby to ustawienie wszystkich elementów na -1.
Nazywa się to „desygnowanymi inicjatorami” , aby uzyskać dodatkowe informacje.
Uwaga: nie jest to zaimplementowane w kompilatorze gcc c ++.
źródło
Strona, do której prowadziłeś link, już dawała odpowiedź na pierwszą część:
Nie ma wbudowanego sposobu na zainicjowanie całej tablicy na jakąś niezerową wartość.
Co do tego, co jest szybsze, stosuje się zwykłą zasadę: „Metoda, która daje kompilatorowi najwięcej swobody, jest prawdopodobnie szybsza”.
po prostu mówi kompilatorowi „ustaw te 100 int na zero”, które kompilator może dowolnie optymalizować.
jest o wiele bardziej szczegółowy. Nakazuje kompilatorowi utworzenie zmiennej iteracyjnej
i
, nakazuje kolejność inicjowania elementów i tak dalej. Oczywiście kompilator prawdopodobnie to zoptymalizuje, ale chodzi o to, że przesadnie określasz problem, zmuszając kompilator do cięższej pracy, aby uzyskać ten sam wynik.Na koniec, jeśli chcesz ustawić tablicę na niezerową wartość, powinieneś (przynajmniej w C ++) użyć
std::fill
:Ponownie, możesz zrobić to samo z tablicą, ale jest to bardziej zwięzłe i daje kompilatorowi więcej swobody. Mówisz tylko, że chcesz wypełnić całą tablicę wartością 42. Nie mów nic o tym, w jakiej kolejności należy to zrobić, ani nic innego.
źródło
C ++ 11 ma inną (niedoskonałą) opcję:
źródło
std::fill(begin(a), end(a), -1)
Za pomocą {} przypisujesz elementy tak, jak są zadeklarowane; reszta jest inicjowana na 0.
Jeśli nie
= {}
można zainicjować, treść jest niezdefiniowana.źródło
Strona, do której prowadziłeś połączenie, ma status
Problem prędkości: Wszelkie różnice byłyby znikome dla tak małych tablic. Jeśli pracujesz z dużymi tablicami, a szybkość jest o wiele ważniejsza niż rozmiar, możesz mieć stałą tablicę wartości domyślnych (zainicjowanych w czasie kompilacji), a następnie
memcpy
modyfikować tablicę.źródło
Innym sposobem inicjalizacji tablicy do wspólnej wartości byłoby wygenerowanie listy elementów w szeregu definicji:
Inicjowanie tablicy do wspólnej wartości można łatwo wykonać:
Uwaga: Wprowadzono DUPx, aby umożliwić podstawienie makr w parametrach do DUP
źródło
W przypadku tablicy elementów jednobajtowych możesz użyć memset, aby ustawić wszystkie elementy na tę samą wartość.
Jest to przykład tutaj .
źródło
Używając tego
std::array
, możemy to zrobić w dość prosty sposób w C ++ 14. Można to zrobić tylko w C ++ 11, ale nieco bardziej skomplikowane.Nasz interfejs jest czasem kompilacji i wartością domyślną.
Trzecia funkcja służy głównie wygodzie, więc użytkownik nie musi sam konstruować
std::integral_constant<std::size_t, size>
, ponieważ jest to dość nieporęczna konstrukcja. Prawdziwa praca jest wykonywana przez jedną z dwóch pierwszych funkcji.Pierwsze przeciążenie jest dość proste: konstruuje
std::array
rozmiar 0. Nie ma potrzeby kopiowania, po prostu go konstruujemy.Drugie przeciążenie jest nieco trudniejsze. Przekazuje dalej wartość otrzymaną jako źródło, a także konstruuje instancję
make_index_sequence
i po prostu wywołuje inną funkcję implementacyjną. Jak wygląda ta funkcja?To konstruuje argumenty pierwszego rozmiaru - 1, kopiując przekazaną przez nas wartość. W tym przypadku wykorzystujemy nasze różnorodne indeksy pakietów parametrów jako coś do rozszerzenia. W tej paczce są wpisy wielkości - 1 (jak określono w konstrukcji
make_index_sequence
) i mają one wartości 0, 1, 2, 3, ..., rozmiar - 2. Jednak nie dbamy o wartości ( więc odrzucamy go, aby wyciszyć wszelkie ostrzeżenia kompilatora). Rozszerzenie pakietu parametrów rozszerza nasz kod do czegoś takiego (przy założeniu rozmiaru == 4):Używamy tych nawiasów, aby zapewnić, że rozszerzenie pakietu variadic
...
rozszerza to, czego chcemy, a także aby upewnić się, że używamy operatora przecinka. Bez nawiasów wyglądałoby na to, że przekazujemy kilka argumentów do inicjalizacji tablicy, ale tak naprawdę oceniamy indeks, rzutujemy go na void, ignorujemy ten wynik void, a następnie zwracamy wartość, która jest kopiowana do tablicy .Ostatni argument, ten, który wzywamy
std::forward
, to drobna optymalizacja. Jeśli ktoś przekaże tymczasowe std :: string i powie „zrób tablicę 5 z nich”, chcielibyśmy mieć 4 kopie i 1 ruch zamiast 5 kopii. Wstd::forward
gwarantuje, że możemy to zrobić.Pełny kod, w tym nagłówki i niektóre testy jednostkowe:
źródło
non_copyable
typ jest w rzeczywistości możliwy do skopiowania za pomocąoperator=
.non_copy_constructible
, że byłaby to dokładniejsza nazwa obiektu. Jednak nigdzie w tym kodzie nie ma przypisania, więc nie ma to znaczenia w tym przykładzie.1) Gdy używasz inicjalizatora, dla struktury lub takiej tablicy, nieokreślone wartości są zasadniczo konstruowane domyślnie. W przypadku typu pierwotnego, takiego jak ints, oznacza to, że zostaną wyzerowane. Zauważ, że dotyczy to rekurencyjnie: możesz mieć tablicę struktur zawierających tablice, a jeśli podasz tylko pierwsze pole pierwszej struktury, wówczas cała reszta zostanie zainicjowana zerami i domyślnymi konstruktorami.
2) Kompilator prawdopodobnie wygeneruje kod inicjujący, który jest co najmniej tak dobry, jak można to zrobić ręcznie. W miarę możliwości wolę pozwolić kompilatorowi wykonać inicjalizację.
źródło
W C ++ można również używać szablonów meta programowania i szablonów variadic. Poniższy post pokazuje, jak to zrobić: Programowo twórz statyczne tablice w czasie kompilacji w C ++ .
źródło
W języku programowania C ++ V4 Stroustrup zaleca używanie wektorów lub wartości zamiast wbudowanych tablic. Dzięki valarrary's, kiedy je utworzysz, możesz zainicjować je do określonej wartości, takiej jak:
Aby zainicjować tablicę 7 członków o długości „7777777”.
Jest to sposób implementacji odpowiedzi w C ++ przy użyciu struktury danych C ++ zamiast „zwykłej starej tablicy C”.
Przerzuciłem się na używanie valarray jako próby w moim kodzie, aby spróbować użyć C ++ 'isms v. C'isms ....
źródło
Powinien być standardową funkcją, ale z jakiegoś powodu nie jest uwzględniony w standardowym C ani C ++ ...
W Fortran można wykonać:
ale nie ma niepodpisanych liczb ...
Dlaczego C / C ++ nie może tego po prostu zaimplementować? Czy to naprawdę takie trudne? To głupie, że trzeba to napisać ręcznie, aby osiągnąć ten sam wynik ...
Co jeśli byłby to tablica o wielkości 1000,00 bajtów? Musiałbym napisać skrypt, aby go napisać dla mnie, lub uciekać się do hacków z asemblerem / etc. To nonsens.
Jest doskonale przenośny, nie ma powodu, aby nie być w języku.
Wystarczy zhakować to w następujący sposób:
Jednym ze sposobów włamania się do niego jest wstępne przetwarzanie ... (Poniższy kod nie obejmuje przypadków skrajnych, ale został napisany, aby szybko zademonstrować, co można zrobić).
źródło
memset
to, nawet z tablicą „na stałe”.