2008-10-26 7 views
55

В некотором коде, который я унаследовал, я часто использую size_t с квалификатором пространства имен std. Например:«std :: size_t» имеет смысл в C++?

std::size_t n = sizeof(long); 

Он компилируется и работает нормально, конечно. Но мне кажется, что это плохая практика (возможно, перенесена с C?).

Не правда ли, что size_t встроен в C++ и, следовательно, в глобальное пространство имен? Нужен ли заголовочный файл для использования size_t в C++?

Другой способ задать этот вопрос, будет следующая программа (с не не включает в себя), как ожидается, компиляции на всех компиляторов C++?

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

C не имеет пространств имен. – wnoise 2008-10-26 02:35:53

+1

Он встроен в C++, когда вы #include , и находится в пространстве имен std. См. Мой ответ ниже. – 2008-10-26 02:38:31

+2

Это не «другой способ задать этот вопрос» - это другой вопрос: main возвращает int. – fizzer 2008-10-26 11:07:13

ответ

126

Там, кажется, путаница среди StackOverflow толпы относительно этого

::size_t определяется в обратной совместимости заголовка stddef.h. Он был частью ANSI/ISO C и ISO C++ с самого начала. Каждая реализация C++ должна поставляться с stddef.h (совместимость) и cstddef, где только последний определяет std::size_t и необязательно ::size_t. См. Приложение D стандарта C++.

2

Иногда другие библиотеки будут определять свой собственный size_t. Например, повышение. std :: size_t указывает, что вам определенно нужен стандартный C++.

size_t является стандартным типом C++ и определяется в пространстве имен std.

+0

Это имеет смысл. Знаете ли вы, что «:: size_t» или «std :: size_t» (или, возможно, оба) являются частью спецификации языка? – jwfearn 2008-10-26 02:16:39

4

size_t не встроен в C++. И он не определяется по умолчанию. Это один не компилируется с GCC:

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

Это говорит, size_t является частью POSIX и если вы используете только базовые вещи, как <cstdlib>, вы, вероятно, в конечном итоге, она определена.

Вы можете утверждать, что std :: size_t является эквивалентом C++ для size_t. Как отметил Брайан, std :: используется как пространство имен, чтобы избежать установки глобальных переменных, которые не подходят всем. Это похоже на std :: string, которая также может быть определена в корневом пространстве имен.

41

Раздел 17.4.1.2 стандарта С ++, пункт 4 гласит, что:

«В стандартной библиотеке C++, однако, заявление и определение (имена, которые определены как макросы в C кроме) находится в пределах пространство имен (3.3.5) пространства имен std. "

Это включает в себя элементы, найденные в заголовках узора CNAME, в том числе cstddef, который определяет size_t.

Так что std :: size_t на самом деле правильный.

13

Вы можете получить size_t в глобальном пространстве имен, включив, например, <stddef.h> вместо <cstddef>. Я не вижу никакой очевидной выгоды, и функция устарела.

+0

Некоторое объяснение нисходящего потока было бы вежливым. Ответ правильный и по теме. – fizzer 2008-10-26 11:32:00

+0

Я не знаю, кто проголосовал за вас. Ваше наблюдение очень важно для первоначального вопроса. – 2008-10-26 15:44:25

1

Коллекторы GNU компилятор содержит что-то вроде

typedef long int __PTRDIFF_TYPE__; 
typedef unsigned long int __SIZE_TYPE__;

Тогда stddef.h constains что-то вроде

typedef __PTRDIFF_TYPE__ ptrdiff_t; 
typedef __SIZE_TYPE__ size_t;

И, наконец, файл cstddef содержит что-то вроде

 
#include <stddef.h> 

namespace std { 

    using ::ptrdiff_t; 
    using ::size_t; 

} 

Я думаю, что должен дать понять. Пока вы включаете <cstddef>, вы можете использовать либо size_t, либо std :: size_t, потому что size_t был набран за пределами пространства имен std и затем был включен. Эффективно у вас есть

typedef long int ptrdiff_t; 
typedef unsigned long int size_t; 

namespace std { 

    using ::ptrdiff_t; 
    using ::size_t; 

} 
2

Я думаю, что разъяснения достаточно ясны. std::size_t имеет смысл в C++ и ::size_t сделать (по крайней мере) здравый смысл в C.

Однако вопрос остается. А именно, можно ли предположить, что ::size_t и std::size_t совместимы?

С чистой точки зрения они не обязательно идентичны, если они не определены где-то, что они должны быть идентичными.

Я думаю, что многие используют что-то а-ля:

---- 
// 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) 
{ 
    ... 
} 

Таким образом, в заголовке вы Defintely использовать ::size_t в то время как в исходном файле вы будете использовать std::size_t. Значит, они должны быть совместимыми, верно? В противном случае вы получите ошибку компилятора.

/Michael S.

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

На самом деле, вы не спросили, что конкретно, кажется, плохая практика ИНТ выше. Использование size_t, квалификация с пространством имен std, ...

Как указано в стандарте C++ (18.1), size_t является типом, определенным в стандартном заголовке. Я предлагаю отказаться от любых мыслей и впечатлений о возможном наследовании с языка C. C++ - это отдельный и другой язык, и лучше рассматривать его как таковой. Он имеет собственную стандартную библиотеку, и все элементы стандартной библиотеки C++ определены в пространстве имен std. Тем не менее, в C++ можно использовать элементы C Standard Library.

Я считаю, что включение в качестве грязного взлома. В стандарте C++ указано, что содержимое заголовков одинаковое или основано на соответствующих заголовках из стандартной библиотеки C, но в ряде случаев были применены изменения. Другими словами, это не прямая копия вставки заголовков C в заголовки C++.

size_t не является встроенным в C++. Это тип, определяющий, какой тип интегрального типа используется как возвращаемый тип оператора sizeof(), поскольку фактический тип возвращаемого значения sizeof() определяется реализацией, поэтому стандарт C++ унифицируется путем определения size_t.

будет следующая программа (без включает в себя), как ожидается, компилировать на все компиляторы C++?

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

Стандарт C++ говорит (1.4):

Имена, определенные в библиотеке есть область пространства имен (7.3). Модуль перевода C++ (2.1) получает доступ к этим именам, включая соответствующий стандартный заголовок библиотеки (16.2).

Размер_t - это имя, определенное в пространстве имен std, поэтому каждая программа, которая использует это имя, должна включать соответствующий заголовок в этом случае.

Далее 3.7.3 глава говорит:

Однако, имея в виду Std, станд :: bad_alloc и станд :: size_t плохо сформированным, если имя не было объявлено, включив соответствующий заголовок.

Учитывая, что программа с использованием size_t, но не включая заголовок, плохо сформирована.

Смежные вопросы