Czy lepiej używać vars niż static const
niż #define
preprocesora? A może to zależy od kontekstu?static const vs #define
Jakie są zalety/wady dla każdej metody?
Czy lepiej używać vars niż static const
niż #define
preprocesora? A może to zależy od kontekstu?static const vs #define
Jakie są zalety/wady dla każdej metody?
Osobiście nienawidzę preprocesora, więc zawsze chodziłem z const.
Główną zaletą #define jest to, że nie wymaga pamięci do przechowywania w programie, ponieważ tak naprawdę po prostu zastępuje jakiś tekst dosłowną wartością. Ma także tę zaletę, że nie ma typu, więc może być użyty dla dowolnej wartości całkowitej bez generowania ostrzeżeń.
Zalety "const" to to, że mogą one być zakresowe i mogą być używane w sytuacjach, w których wskaźnik do obiektu musi zostać przekazany.
Nie wiem dokładnie, co robisz ze "statyczną" częścią. Jeśli deklarujesz globalnie, umieściłbym to w anonimowym obszarze nazw zamiast używać statycznego. Na przykład
namespace {
unsigned const seconds_per_minute = 60;
};
int main (int argc; char *argv[]) {
...
}
To właśnie chcę wiedzieć. W mojej firmie strategia polega na tym, aby cały ciąg stał się ciągiem #define w osobnym pliku. Myślałem, że może lepiej użyć zamiast tego vars const. Dzięki –
* Ciąg * stałe są jednym z tych, które mogą skorzystać z '# define'd, przynajmniej jeśli mogą być użyte jako" klocki "dla większych stałych ciągów.Zobacz moją odpowiedź na przykład. – AnT
Sprawa, której nie rozważałam. Dziękuję za Twój czas. –
Używanie statycznej stałej jest jak używanie innych zmiennych stałych w kodzie. Oznacza to, że możesz śledzić, skąd pochodzą informacje, w przeciwieństwie do # definicji, które zostaną po prostu zastąpione w kodzie w procesie wstępnej kompilacji.
Czasami warto spojrzeć na C++ FAQ Lite dla tego pytania: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7
można znaleźć tutaj: static const vs define
zwykle const deklaracji (Zauważ, że nie musi być statyczny) to sposób, aby przejść
Jeśli jest to C++ pytanie wymienia #define
jako alternatywa, to jest o „globalne” (czyli plików Zakres), a nie o stałych członków klasy. Jeśli chodzi o takie stałe w C++ static const
jest zbędny. W C++ const
mają domyślnie wewnętrzne powiązania i nie ma sensu deklarować ich jako static
. Tak naprawdę jest to około const
vs. #define
.
I na koniec w C++ const
jest preferowany. Przynajmniej dlatego, że takie stałe są wpisane i mają zasięg. Po prostu nie ma powodów, aby preferować #define
ponad const
, poza kilkoma wyjątkami.
Stałe łańcuchowe, BTW, są jednym z przykładów takiego wyjątku. Z #define
stałych d ciąg można użyć w czasie kompilacji funkcji połączeniem kompilatory C/C++, jak w
#define OUT_NAME "output"
#define LOG_EXT ".log"
#define TEXT_EXT ".txt"
const char *const log_file_name = OUT_NAME LOG_EXT;
const char *const text_file_name = OUT_NAME TEXT_EXT;
PS: Znowu, na wszelki wypadek, gdy ktoś wymienia static const
jako alternatywę dla #define
, zwykle oznacza to, że mówią o C, a nie o C++. Zastanawiam się, czy to pytanie jest oznaczone prawidłowo ...
Zwykle powinieneś preferować statyczne consts.Nie ma żadnych wad. Procesor powinien być używany głównie do kompilacji warunkowej (a czasem dla naprawdę brudnych sztuczek).
Plusy i minusy do wszystkiego, w zależności od sposobu użytkowania:
enum class X
są ujednoznaczniane za pomocą zakresu silnie wpisanego, ale do wielkości int o dużym sygnaturach lub niepodpisanych, na które nie masz wpływu w C++ 03 (chociaż możesz określić pole bitowe, w którym powinny być spakowane, jeśli enum jest członkiem struct/class/union), podczas gdy C++ 11 domyślnie jest int
, ale może być jawnie ustawione przez programistętemplate <typename T> void f(T t) { cout << ++t; }
nie będzie się kompilować, ale można zawrzeć wyliczenie w klasie z niejawnym konstruktorem, operatorem odlewania i operatorami definiowanymi przez użytkownika).template <typename T> void f(T)
uzyskać wyraźną instancję po przekroczeniu ta sama wartość liczbowa z różnych tabel, z których każda różni się od rzeczywistej instancji f(int)
. Kod obiektu każdej funkcji może być identyczny (ignorując przesunięcia adresów), ale nie spodziewałbym się, że kompilator/linker wyeliminuje niepotrzebne kopie, chociaż mógłbyś sprawdzić kompilator/linker, jeśli ci na tym zależy.enum { A = 1, B = 2 }
- jest A|B
"legalne ? "z punktu widzenia logiki programu)make
i inne narzędzia do ponownej kompilacji oparte na znacznikach czasowych spowodują ponowne rekompilowanie klienta, gdy zostaną zmienione (złe!)#define
ala #define S std::string("abc")
, ale stały unika powtarzalna konstrukcja odrębnych tymczasników w każdym punkcie użyciaconst
, co minimalizuje wpływ pracy i jeśli przełączanie pomiędzy wartością dwa#define X "x"
i pewnego użytkowania klienta ala "pre" X "post"
, jeśli chcesz lub musisz zrobić Xa zmiennej runtime-zmienny niż stały wymusić zmiany w kodzie klienta (zamiast po prostu ponownej kompilacji), podczas gdy przejście to jest łatwiejsze od const char*
lub const std::string
, biorąc pod uwagę, że już zmuszają użytkownika do włączenia konkat operacje enacyjne (np. "pre" + X + "post"
do string
)sizeof
bezpośrednio określona numeryczny dosłownymunsigned
){ 1, 2 }
, które mogą być użyte do inicjalizacji tablic, lub #define MICROSECONDS *1E-6
itd. (zdecydowanie nie polecając to!)__FILE__
i __LINE__
mogą zostać włączone do makra#if
sprawozdania za warunkowo tym kod (mocniejszy niż post- wstępne przetwarzanie "jeśli", ponieważ kod nie musi być kompilowany, jeśli nie został wybrany przez preprocesor), należy użyć #undef
-ty, ponownie zdefiniować itd.make
i inne narzędzia rekompilacji datownika oparte wywoła rekompilacji klienta, gdy są one zmieniane (zły!)Zasadniczo używam const
s i uważam je za najbardziej profesjonalną opcję ogólnego zastosowania (chociaż inne mają prostotę, która przemawia do tego starego leniwego programisty).
+1: Doceń podsumowanie – Chubsdad
Niesamowita odpowiedź. Jeden mały nit: czasami używam lokalnych wyliczeń, które nie są w nagłówkach w ogóle dla jasności kodu, jak w małych maszynach państwowych i tym podobnych. Nie muszą więc przez cały czas znajdować się w nagłówkach. – kert
@kert: stały punkt ... odpowiednio edytował. Dzięki. –
Definiowanie stałych za pomocą dyrektywy preprocesora #define
nie jest zalecane do stosowania nie tylko w C++
, ale także w C
. Te stałe nie będą miały tego typu. Nawet w C
zaproponowano użycie stałych stałych w postaci const
.
Jeśli definiujesz stałą, która ma być współużytkowana wśród wszystkich wystąpień klasy, użyj statycznej stałej. Jeśli stała jest specyficzna dla każdej instancji, po prostu użyj const (pamiętaj jednak, że wszystkie konstruktory klasy muszą zainicjować tę zmienną składową const na liście inicjalizacji).
Zawsze preferuj korzystanie z funkcji językowych w stosunku do niektórych dodatkowych narzędzi, takich jak preprocesor.
ES.31: Nie używać makr dla stałych lub „funkcjach”
makra są głównym źródłem błędów. Makra nie są zgodne ze zwykłymi zakresami i regułami typu. Makra nie są zgodne ze zwykłymi regułami przekazywania danych. Makra zapewniają, że ludzki czytelnik widzi coś innego niż to, co widzi kompilator. Makra komplikują tworzenie narzędzi.
Scott Meyers uwzględnia tę kwestię bardzo ładnie i dokładnie. Jego przedmiot nr 2 w "Effective C++ Third Edition". Dwa specjalne przypadki (1) statyczna const jest preferowana w zakresie klasy dla stałych specyficznych dla klasy; (2) przestrzeń nazw lub anonimowy zakres jest preferowany w stosunku do #define. – Eric
Wolę Enums. Ponieważ jest hybrydą obu. Nie zajmuje miejsca, chyba że utworzysz jego zmienną. Jeśli chcesz tylko użyć jako stałej, wyliczenie jest najlepszą opcją. Ma typ bezpieczeństwa w C/C++ 11 std, a także idealną stałą. #define jest typu niebezpiecznego, const zajmuje miejsce, jeśli kompilator nie może go zoptymalizować. – siddhusingh
Moja decyzja dotycząca użycia '# define' lub' static const' (dla ciągów) jest sterowana przez ** aspekt inicjalizacji ** (nie było to wspomniane w poniższych odpowiedziach): jeśli stała jest używana tylko w określonej jednostce kompilacji, to Używam 'static const', w przeciwnym razie używam' # define' - unikam inicjalizacji kolejności statycznej ** fiasko ** https://isocpp.org/wiki/faq/ctors#static-init-order –