Типы векторного размера C ++ - PullRequest
16 голосов
/ 03 октября 2011

Я только начал изучать C ++ и у меня есть вопрос о векторах.В книге, которую я читаю, говорится, что если я хочу извлечь размер вектора типа double (например), я должен сделать что-то вроде:

vector<double>::size_type vector_size;
vector_size = myVector.size();

Тогда как в Java я мог бы сделать

int vector_size;
vector_size = myVector.size();

Мой вопрос: почему существует тип с именем vector :: size_type?Почему C ++ не использует только int?

Ответы [ 5 ]

23 голосов
/ 03 октября 2011

C ++ - это язык для написания библиотек *, и одной из его сильных сторон является то, чтобы автор был как можно более общим. Вместо того, чтобы предписывать стандартным контейнерам использовать какой-либо конкретный тип данных, более общий подход состоит в том, чтобы указывать, что каждый контейнер предоставляет тип элемента size_type. Это обеспечивает большую гибкость и универсальность. Например, рассмотрим этот общий код:

template <template <typename...> Container, typename T>
void doStuff(const Container<T> & c)
{
  typename Container<T>::size_type n = c.size();
  // ...
}

Этот код будет работать на любом шаблоне контейнера (который может быть создан с помощью одного аргумента), и мы не налагаем никаких ненужных ограничений на пользователя нашего кода.

(На практике большинство типоразмеров разрешается до std::size_t, который, в свою очередь, является типом без знака, обычно unsigned int или unsigned long - но почему мы должны это знать?)

*) Я не уверен, каким будет соответствующее утверждение для Java.

6 голосов
/ 03 октября 2011

Java не имеет целочисленных типов без знака, поэтому они должны идти с int.

Наоборот, C ++ использует и использует их там, где это необходимо (где отрицательные значения не имеют значения), каноническим примером является длиначто-то вроде массива.

3 голосов
/ 03 октября 2011

Стандарт C ++ говорит, что контейнер size_type является целым типом без знака, но не указывает, какой;одна реализация может использовать unsigned int, а другая может использовать, например, unsigned long.

C ++ не "экранирован" от деталей реализации для конкретной платформы, как Java.Псевдоним size_type помогает защитить ваш код от таких деталей, поэтому он будет работать правильно независимо от того, какой фактический тип должен использоваться для представления размера вектора.

1 голос
/ 03 октября 2011

В книге, которую вы читаете, говорится, что если вы хотите извлечь размер вектора типа double (например), вы должны сделать что-то вроде:

    vector<double>::size_type vector_size;
    vector_size = myVector.size();

В то время как в Java вы могли бы сделать

    int vector_size;
    vector_size = myVector.size();

Оба варианта являются худшими в C ++.Первый является чрезвычайно многословным и небезопасным (в основном из-за неявного продвижения по службе).Второй - многословный и крайне небезопасный (из-за диапазона номеров).

В C ++ выполните

    ptrdiff_t const vectorSize = myVector.size();

Обратите внимание, что

  • ptrdiff_tиз заголовка stddef.h является типом со знаком, который гарантированно достаточно большой.

  • Инициализация выполняется в объявлении (это лучше в стиле C ++).

  • Обе переменные одинаковые были применены к обеим переменным.

Таким образом, правильные действия короче и безопаснее.

Приветствия & hth.,

1 голос
/ 03 октября 2011

Мое личное мнение по этому поводу состоит в том, что это для лучшей безопасности кода / читаемости.

Для меня int - это тип, который не несет особого значения: он может нумеровать яблоки, бананы или что-либо еще.

size_type, что, вероятно, typedef для size_t, имеет более сильное значение: оно указывает размер в байтах.

То есть легче узнать, что означает переменная. Конечно, после этого обоснования может быть много разных типов для разных юнитов. Но «размер буфера» действительно распространенный случай, поэтому он как-то заслуживает выделенного типа.

Другим аспектом является поддержка кода: если контейнер внезапно изменит свой size_type, скажем, с uint64_t на unsigned int, например, используя size_type, вам не нужно изменять его в каждом исходном коде, полагаясь на него. .

...