Мне действительно нужно возвращать Type :: size_type? - PullRequest
4 голосов
/ 22 апреля 2010

У меня часто бывают классы, которые в основном являются просто обертками вокруг некоторого контейнера STL, например:

class Foo {
public:
  typedef std::vector<whatever> Vec;
  typedef Vec::size_type size_type;
  const Vec& GetVec() { return vec_; }
  size_type size() { return vec_.size() }
private:
  Vec vec_;
};

Я не уверен в возвращении size_type. Часто какая-то функция вызывает size() и передает это значение другой функции, которая будет использовать его и, возможно, передавать его дальше. Теперь каждый должен включить этот заголовок Foo, хотя я просто передаю некоторое значение размера, которое в любом случае должно быть unsigned int ...? Что правильно делать здесь? Разве лучше всего использовать size_type везде?

Ответы [ 5 ]

7 голосов
/ 22 апреля 2010

STL определяет эти типы как абстрактный интерфейс для контейнеров.Он предназначен для поддержки любого типа резервного хранилища.Это может быть NUMA или дисковое хранилище, где size_type и ptr-type отличаются от тех, которые используются для системной памяти.Или - в архитектуре NUMA - это может быть конкретный узел памяти, который быстр и может работать с очень маленькими size_type и ptr_type - что является подходящей оптимизацией для многих архитектур.

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

Тем не менее, насколько это вам больно?Это было бы правильно.

6 голосов
/ 22 апреля 2010

Это должно быть vector<>::size_type, как у вас, это самый правильный путь.

Тем не менее, я знаю, что многие люди, включая меня, будут просто использовать size_t вместо этого. Хотя не обязательно быть одинаковым, vector<>::size_type - это size_t для каждой реализации, которую я знаю. Вам должно быть хорошо с этим.

5 голосов
/ 22 апреля 2010

На самом деле это должен быть size_t, а не unsigned int, для 64-битной совместимости.Как писатель класса-оболочки, я бы вернул size_type.Как клиент класса, я бы привел его к соответствующему типу (size_t), если это более удобно.

1 голос
/ 23 апреля 2010

Я не уверен в возвращении size_type. Часто некоторые функции вызовите size () и передайте это значение другая функция, и эта будет использовать это и, возможно, передать его. Теперь все должен включать этот заголовок Foo ...

Это нормально, чтобы вернуть size_type, но это не значит, что другая функция должна обязательно принимать тот же size_type, что и typedeffed в вашем классе. Существуют преобразования между целочисленными типами. Будь смелым и просто используй size_t.

Вы все равно не можете перегрузить функции, так что будет одна, которая работает с size вектора, другая для размера deque и т. Д., На случай, если все они используют другой size_type (который стандарт наверное разрешает). - Но вы также можете использовать шаблоны, если это возможно, чтобы вывести правильный size_type для использования из аргумента.

0 голосов
/ 22 апреля 2010

Один вариант, который вы могли бы рассмотреть - наследование от std::vector:

typedef std::vector<whatever> Foo_Vec;

class Foo : public Foo_Vec
{
public:
    const Foo_Vec &GetVec() { return (Foo_Vec&)*this; }
};

Я ни в коем случае не говорю, что это лучший подход, поскольку он может привести к проблемам, которые не возникнут при наличии закрытого члена или наследовании от private Foo_Vec, поскольку public Foo_Vec предоставляет все методы от std::vector до Foo. Более того, std::vector не имеет виртуального деструктора, поэтому, если вы попытаетесь очистить коллекцию std::vector с помощью Foo, она не будет полностью очищена. Я просто выбрасываю это туда.

Как показывают другие ответы, вы должны использовать size_t или size_type вместо unsigned int для 64-битной совместимости. В противном случае в будущей 64-разрядной сборке ваш std::vector может содержать более 2 32 элементов, но значение размера будет усечено, что приведет к ошибкам.

...