Где я могу найти определение size_type для векторов в C++ STL?

Кажется безопасным преобразовать результат моей векторной функции size() в unsigned int. Но как я могу сказать наверняка? В моей документации не совсем ясно, как определяется size_type.

Почему вы хотите передать результат чему-то еще? Тот факт, что вы получаете несоответствие типов, указывает на то, что в вашем коде что-то не так, что необходимо (или должно) быть исправлено (вот почему C++ имеет СИЛЬНУЮ типизацию). Не пытайтесь свернуть систему типов.

Martin York 22.10.2008 21:22

Что, если ему нужно передать размер контейнера какому-то существующему коду, который использует, скажем, беззнаковое целое число?

J Francis 22.10.2008 21:43

Тогда ему не повезло, потому что в 64-битной системе vector :: size_type вполне может быть больше, чем unsigned int.

Steve Jessop 23.10.2008 01:32

@JF: Тогда просто оставьте предупреждение или исправьте код, который вы вызываете. Не приводите тип, чтобы удалить предупреждение, это просто нарушит код, когда вы перейдете в новую систему, где ваши предположения не работают.

Martin York 23.10.2008 03:24

Или удалите предупреждение, но добавьте утверждение (желательно во время компиляции), которое срабатывает, когда предположение не выполняется. В GCC, например, есть старый трюк с объявлением char [sizeof (unsigned int) - sizeof (size_type)], который взрывается, когда разница отрицательная.

Steve Jessop 23.10.2008 07:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
5
8 705
7

Ответы 7

По стандарту ты не можешь быть уверен. Точный тип зависит от вашей машины. Тем не менее, вы можете посмотреть определение в реализациях заголовка вашего компилятора.

Я попытался заглянуть в заголовки. Пройдя целый лабиринт общих определений, я зашел в тупик в файле под названием xmemory, где упоминается тип size_t. Согласно моей IDE size_t нигде не определено!

Tommy Herbert 22.10.2008 19:54

Ага - чтение заголовков библиотек (особенно основанных на шаблонах) может быть настоящей головной болью.

Michael Burr 22.10.2008 19:56

По крайней мере, в gcc заголовок, который фактически определяет size_t (stddef.h), похоронен где-то еще, далеко от обычных include (/usr/lib/gcc/.../include вместо / usr / include).

CesarB 22.10.2008 20:20

size_t - это стандартное определение типа C. Посмотрите cstddef, который, вероятно, приведет вас к stddef.h (cplusplus.com/reference/clibrary/cstring/size_t.html). На самом деле, как и NULL, большинство знакомых мне программистов не включают cstddef перед использованием size_t. Честно говоря, size_t, вероятно, будет целым числом без знака.

Max Lybbert 22.10.2008 20:46

В общем, вы должны использовать size_t там, где у вас может возникнуть соблазн использовать unsigned int. Для обоих типов вы не можете быть уверены, сколько битов они содержат, но в случае size_t вы должны быть уверены, что может достаточно велик, чтобы измерить размер вещей в памяти.

ejgottl 22.10.2008 21:04

Вопрос в том, зачем вам это нужно?

Martin York 22.10.2008 21:20

@ Мартин: Зачем тебе что? Определить, может ли int содержать size_type? Если это то, о чем вы спрашиваете, то, как JF несколько раз упоминал, это может быть из-за того, что вы передаете его в API или что-то, что вы не контролируете, что хочет int.

Michael Burr 22.10.2008 22:59

Пока вы уверены, что unsigned int в вашей системе будет достаточно большим, чтобы вместить количество элементов, которые у вас будут в векторе, вы должны быть в безопасности ;-)

Но это делает код не порталом. Все дело в том, чтобы писать хороший код.

Martin York 22.10.2008 21:18

"до тех пор, пока .. unsigned int .. будет достаточно большим". Это то, что Томми пытается выяснить. Это не ответ.

Aaron 22.10.2008 21:18

Точно! Всякий раз, когда вы выполняете приведение, вы переопределяете систему типов, поэтому вам нужно знать, что вы делаете.

J Francis 22.10.2008 21:32

@Aaron: Я думаю, вы неправильно поняли ответ JF. Он указывает, что это безопасно, если фактический размер вектора во время выполнения не превышает UINT_MAX. Это более слабое условие, чем то, что ширина size_type не больше ширины unsigned int.

Steve Jessop 23.10.2008 01:38

Я не могу себе представить, что это было бы небезопасно в 32-битной системе, но 64-битная версия может быть проблемой (поскольку ints остаются 32-битными). На всякий случай, почему бы просто не объявить вашу переменную vector <MyType> :: size_type вместо unsigned int?

Это то, что я сделал, но мне все еще любопытно, как искать информацию в STL.

Tommy Herbert 22.10.2008 20:24

@Tommy: У тебя уже есть вся необходимая информация. Приведение небезопасно, вместо этого следует использовать "vector <MyType> :: size_type". или size_t. Если вы только любопытный, что это такое, спросите компилятор: cout << typeid (size_t) .name () << "\ n"; // если вы спросите вежливо, он может вам сказать.

Aaron 22.10.2008 21:17

Я не уверен, насколько хорошо это будет работать, потому что я просто мысленно думаю, но утверждение времени компиляции (например, BOOST_STATIC_ASSERT() или см. Способы выполнения выражений ASSERT во время сборки в C) может помочь. Что-то типа:

BOOST_STATIC_ASSERT( sizeof( unsigned int) >= sizeof( size_type));

Но почему. Предположение, что здесь работает тип, не поможет при публикации кода.

Martin York 22.10.2008 21:19

Может быть, я что-то неправильно понимаю - если компилятор может проверить, что любой тип, в который вы хотите, чтобы размер входил, по крайней мере, такой же большой, как тип, который вы получаете из size (), разве это не отвечает на вопрос OP? Даже если это не решит проблему автоматически

Michael Burr 22.10.2008 22:28

Обратите внимание, что я предположил, что OP хочет преобразовать size_type в int, потому что он передает результат size () функции / методу / структуре / тому, что хочет int и не находится под его контролем.

Michael Burr 22.10.2008 22:35

Всегда должно быть безопасно преобразовать его в size_t. unsigned int недостаточно в большинстве 64-битных систем, и даже unsigned long недостаточно в Windows (которая использует модель LLP64 вместо модели LP64, которую используют большинство Unix-подобных систем).

Не предполагайте тип размера контейнера (или что-то еще, введенное внутри).

Сегодня?

Лучшее решение на данный момент - использовать:

std::vector<T>::size_type

Где Т твой тип. Например:

std::vector<std::string>::size_type i ;
std::vector<int>::size_type j ;
std::vector<std::vector<double> >::size_type k ;

(Использование typedef может помочь облегчить чтение)

То же самое касается итераторов и всех других типов "внутри" контейнеров STL.

После C++ 0x?

Когда компилятор сможет найти тип переменной, вы сможете использовать ключевое слово auto. Например:

void doSomething(const std::vector<double> & p_aData)
{
    std::vector<double>::size_type i = p_aData.size() ; // Old/Current way

    auto j = p_aData.size() ;    // New C++0x way, definition
    decltype(p_aData.size()) k;  // New C++0x way, declaration
}

Обновлено: вопрос от JF

What if he needs to pass the size of the container to some existing code that uses, say, an unsigned int? – JF

Это проблема, типичная для использования STL: вы не можете сделать это без некоторой работы.

Первое решение - разработать код, чтобы всегда использовать тип STL. Например:

typedef std::vector<int>::size_type VIntSize ;

VIntSize getIndexOfSomeItem(const std::vector<int> p_aInt)
{
   return /* the found value, or some kind of std::npos */
}

Второй - выполнить преобразование самостоятельно, используя либо static_cast, используя функцию, которая будет утверждать, если значение выходит за пределы целевого типа (иногда я вижу код, использующий «char», потому что «знаете, индекс никогда не выйдет за пределы 256» [цитирую из объем памяти]).

Я считаю, что это сам по себе полный вопрос.

Что, если ему нужно передать размер контейнера какому-то существующему коду, который использует, скажем, беззнаковое целое число?

J Francis 22.10.2008 21:33

На практике (и при использовании стандартных контейнеров) size_type можно заменить на size_t. Вот обсуждение этого: velocityreviews.com/forums/t281965-sizet-and-sizetype.html

vividos 23.10.2008 13:33

В стандарте C++ указано только, что size_t находится в <cstddef>, что помещает идентификаторы в <stddef.h>. Моя копия Харбисон и Стил помещает минимальные и максимальные значения для size_t в <stdint.h>. Это должно дать вам представление о том, насколько большой должна быть переменная получателя для вашей платформы.

Лучше всего придерживаться целочисленных типов, которые достаточно велики, чтобы удерживать указатель на вашей платформе. В C99 это будут intptr_t и uintptr_t, также официально расположенные в <stdint.h>.

Другие вопросы по теме