2008-10-26 15 views
55

W jakimś kodzie odziedziczonym często używam size_t z kwalifikatorem przestrzeni nazw std. Na przykład:Czy "std :: size_t" ma sens w C++?

std::size_t n = sizeof(long); 

Kompiluje i działa dobrze, oczywiście. Ale wydaje mi się to złą praktyką (być może przeniesioną z C?).

Czy to prawda, że ​​size_t jest wbudowany w C++, a zatem w globalnym obszarze nazw? Czy plik nagłówkowy jest potrzebny do korzystania z C++ w wersji size_t?

Innym sposobem na to pytanie jest, że następujący program (z nie obejmuje) należy oczekiwać skompilować na wszystkie kompilatory C++?

size_t foo() 
{ 
    return sizeof(long); 
} 
+9

C nie ma przestrzeni nazw. – wnoise

+1

Jest on wbudowany w C++, gdy #nutlude i jest w standardowej przestrzeni nazw. Zobacz moją odpowiedź poniżej. –

+2

To nie jest "inny sposób zadawania tego pytania" - to inne pytanie: główne zwroty int. – fizzer

Odpowiedz

126

Wydaje się, że zamieszanie wśród tłumu stackoverflow dotyczącej tego

::size_t jest określony w nagłówku wstecznej kompatybilności stddef.h. Od samego początku było częścią ANSI/ISO C i ISO C++. Każda implementacja C++ musi być dostarczana z stddef.h (zgodność) i cstddef, gdzie tylko ta ostatnia definiuje std::size_t i niekoniecznie ::size_t. Patrz załącznik D do standardu C++.

+12

Absolutnie najlepsza odpowiedź tutaj. Opiera się na standardzie zamiast na określonym kompilatorze. Odpowiada na oryginalne pytanie bez zbaczania w dół stycznych. – Darryl

+2

Kolejny powód, by nie używać 'using namespace std' –

+0

@Darryl: Aby być uczciwym, wszystkie starsze odpowiedzi też tak zrobiły. –

2

Czasami inne biblioteki definiują swój własny size_t. Na przykład doładowanie. std :: size_t określa, że ​​zdecydowanie potrzebujesz standardowego C++.

size_t jest standardowym typem C++ i jest zdefiniowany w standardowej przestrzeni nazw.

+0

To ma sens. Czy wiesz, czy ":: size_t" lub "std :: size_t" (lub może oba) są częścią specyfikacji językowej? – jwfearn

4

size_t nie jest wbudowany w C++. I nie jest to domyślnie zdefiniowane. Ten jeden nie skompilować z GCC:

int main(int argc, char** argv) { 
size_t size; 
} 

Powiedział, że size_t jest częścią POSIX i jeśli używasz tylko podstawowe rzeczy jak <cstdlib>, będzie prawdopodobnie w końcu o to zdefiniowane.

Można argumentować, że std :: size_t jest odpowiednikiem C++ w size_t. Jak zauważył Brian, std :: jest używany jako przestrzeń nazw, aby uniknąć ustawiania zmiennych globalnych, które nie pasują do wszystkich. Jest to podobne do std :: string, które można również zdefiniować w głównej przestrzeni nazw.

41

Sekcja 17.4.1.2 standardu C++, pkt 4 stanowi, że:

„W C++ Standard Library jednak deklaracje i definicje (z wyjątkiem nazw, które są zdefiniowane jako makra w C) znajdują się w Przestrzeń nazw (3.3.5) standardu przestrzeni nazw. "

Obejmuje to przedmioty znalezione w nagłówkach wzoru cname, w tym cstddef, który określa size_t.

Tak więc std :: size_t jest w rzeczywistości poprawny.

13

Można uzyskać size_t w globalnym obszarze nazw, dodając na przykład <stddef.h> zamiast <cstddef>. Nie widzę żadnych widocznych korzyści, a funkcja jest przestarzała.

+0

Kilka wyjaśnień dotyczących upadku byłoby uprzejmych. Odpowiedź jest poprawna i na temat. – fizzer

+0

Nie wiem, kto zagłosował. Twoja obserwacja bardzo wskazuje na oryginalne pytanie. –

+0

Głosowałem za tobą, głównie dlatego, że istnieje niezastrzeżony sposób robienia tego: deklaracje użycia, czyli 'using std :: size_t', i nie wspominałeś o tym, że jest to lepsza alternatywa. :-) – cic

1

Nagłówki GNU Compiler zawierać coś takiego

typedef long int __PTRDIFF_TYPE__; 
typedef unsigned long int __SIZE_TYPE__;

Następnie stddef.h constains coś

typedef __PTRDIFF_TYPE__ ptrdiff_t; 
typedef __SIZE_TYPE__ size_t;

I wreszcie plik cstddef zawiera coś

 
#include <stddef.h> 

namespace std { 

    using ::ptrdiff_t; 
    using ::size_t; 

} 

myślę, że powinien to wyjaśnić. Jeśli podasz <cstddef>, możesz użyć albo size_t albo std :: size_t, ponieważ size_t zostało wpisane poza obszarem nazw standardowych i zostało wtedy dołączone. Skutecznie masz

+0

Więc GNU definiuje to w ten sposób, nie to znaczy, że wszystkie kompilatory? Czy standard mówi, że tak musi być? – anthropomorphic

2

Myślę, że wyjaśnienia są wystarczająco jasne. Model std::size_t ma sens w C++ i ::size_t co najmniej (przynajmniej) w sensie C.

Pozostaje jednak pytanie. Mianowicie, czy można bezpiecznie założyć, że ::size_t i std::size_t są kompatybilne?

Z perspektywy czystych typów nie zawsze są identyczne, chyba że zdefiniowano gdzieś, że muszą być identyczne.

myślę, że wielu korzysta coś a la:

---- 
// a.hpp 
#include <string> 

void Foo(const std::string & name, size_t value); 

----- 
// a.cpp 
#include "a.hpp" 

using namespace std; 

void Foo(const string & name, size_t value) 
{ 
    ... 
} 

Więc w nagłówku ty z pewnością użyć ::size_t natomiast w pliku źródłowym użyjesz std::size_t. Więc muszą być kompatybilne, prawda? W przeciwnym razie wystąpi błąd kompilatora.

/Michael S.

+2

:: size_t nie ma sensu w C, który nie ma przestrzeni nazw. –

4
std::size_t n = sizeof(long); 

Właściwie to nie zapytał, co wydaje się być szczególnie złą praktyką int powyższych. Używanie size_t, kwalifikacja z std namespace, ...

Jak mówi standard C++ (18.1), size_t jest typem zdefiniowanym w nagłówku standardowym. Proponuję upuścić wszelkie myśli i wrażenia na temat możliwego dziedzictwa z języka C. C++ jest oddzielnym i innym językiem i lepiej go traktować jako taki. Ma własną standardową bibliotekę i wszystkie elementy Standardowej Biblioteki C++ są zdefiniowane w standardowej przestrzeni nazw. Jednak możliwe jest korzystanie z elementów C Standard Library w programie C++.

Zastanowiłbym się, jako brudny hack. Standard C++ stwierdza, że ​​zawartość nagłówków jest taka sama lub bazuje na odpowiednich nagłówkach z C Standard Library, ale w wielu przypadkach zastosowano zmiany. Innymi słowy, nie jest to bezpośrednia kopia nagłówków C w nagłówkach C++.

size_t nie jest wbudowanym typem w C++. Jest to typ zdefiniowany w celu określenia, jaki rodzaj typu integralnego jest używany jako typ zwracany przez operator sizeof(), ponieważ rzeczywisty typ zwracanego sizeof() jest zdefiniowany w implementacji, więc standard C++ ujednolica definiując size_t.

będzie (obejmuje bez ) należy spodziewać się następujący program skompilować na wszystkie kompilatory C++?

size_t foo() 
{ 
    return sizeof(long); 
} 

C++ standard mówi (1.4):

Nazwy zdefiniowane w bibliotece mają zakres przestrzeni nazw (7.3). Jednostka tłumaczeniowa języka C++ (2.1) uzyskuje dostęp do tych nazw przez uwzględnienie odpowiedniego standardowego nagłówka biblioteki (16.2).

Wielkość_t jest nazwą zdefiniowaną w ramach przestrzeni nazw standardowej, więc każdy program, który używa tej nazwy, powinien w tym przypadku zawierać odpowiedni nagłówek.

Następnie rozdział 3.7.3 mówi:

Jednakże, odnosząc się do std std :: bad_alloc i std :: size_t jest źle sformułowane, chyba że nazwa została uznana za tym odpowiedni nagłówek.

Biorąc pod uwagę, że program używający size_t, ale bez nagłówka, jest źle sformułowany.

Powiązane problemy