Имеет ли" std::size t " смысл в C++?


в некотором коде, который я унаследовал, я вижу частое использование size_t С std квалификатор пространства имен. Например:

std::size_t n = sizeof( long );

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

разве это не правда, что size_t встроен в C++ и, следовательно, в глобальное пространство имен? Является ли заголовочный файл включить необходимо использовать size_t в C++?

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

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

8 ответов:

кажется, что есть путаница среди толпы stackoverflow по этому поводу

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

В разделе 17.4.1.2 стандарта C++, пункт 4, говорится, что:

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

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

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

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

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

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

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

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

std::size_t n = sizeof( long );

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

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

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

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

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

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

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

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

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

далее, в главе 3.7.3 говорится:

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

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

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

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

заголовки компилятора GNU содержат что-то вроде

typedef long int __PTRDIFF_TYPE__;
typedef unsigned long int __SIZE_TYPE__;

затем stddef.h константы что-то вроде

typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;

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

#include <stddef.h>

namespace std {

  using ::ptrdiff_t;
  using ::size_t;

}

Я думаю, что это должно быть ясно. Пока вы включаете , вы можете использовать либо 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;

}

Я думаю, что разъяснения достаточно ясны. Элемент 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 ) 
{
  ...
}

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

/ Michael S.