Как правильно определить тип и указатель того же типа? - PullRequest
4 голосов
/ 12 августа 2010

Как правильно определить тип и указатель того же типа? Вот что я имею в виду. Должен ли я сделать это:

typedef unsigned int delay;
typedef unsigned int * delayp;

Или я должен сделать это:

typedef unsigned int delay;
typedef delay * delayp;

Или, возможно, мне вообще не следует указывать typedef, а просто используйте delay * вместо delayp везде, где я нахожу необходимым?

Спасибо, Бода Цидо.

Ответы [ 6 ]

26 голосов
/ 12 августа 2010

Правильный путь - не делать это. Скрытие того факта, что что-то является указателем, обычно считается плохим стилем.

3 голосов
/ 12 августа 2010

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

Это также плохая форма, потому что если у вас есть:

typedef T* T_ptr;

Тогда const T* foo и const T_ptr bar - две совершенно разные вещи. (foo - это указатель на const T; это обещание не изменять объект через этот указатель. bar - это сам указатель const; его нельзя изменить, чтобы он указывал на что-то другое. )

Первый случай (указатель на const) важен: он помогает обеспечить выполнение контрактов функций.

Второй случай гораздо, гораздо менее полезен.

Поэтому, если бы вы добавили typedef для типа указателя, чтобы быть полезным, вам нужно создать два:

typedef T* T_ptr;
typedef const T* const_T_ptr;

Допустимое исключение в C ++, когда у вас есть классы интеллектуальных указателей. В этих случаях ввод boost::shared_ptr<T> может быть достаточно утомительным, так как создание typedef для этого является разумным удобством.

3 голосов
/ 12 августа 2010

typedef unsigned int delay, * delayp;

2 голосов
/ 12 августа 2010

Как правило, вы делаете второй блок, потому что вы повторно используете тип. Например, если delay требуется, чтобы он стал unsigned long, определение delayp изменять не нужно.

Тем не менее, прятать указатели за typedef обычно очень плохая идея. Это более приемлемо для вещей, которые действуют как указатели, как итераторы или умные указатели:

typedef std::vector<int> my_container;
typedef my_container::iterator my_iterator;

typedef some_type<blah> my_type;
typedef shared_ptr<my_type> my_shared_ptr;
0 голосов
/ 12 августа 2010

Ваша вторая форма

typedef delay * delayp;
лучше, потому что, если вы захотите в будущем изменить typedef «delay» с int на что-то другое (например, long), вы можете сделать это изменение только в одном месте.

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

0 голосов
/ 12 августа 2010

В случае int это не должно иметь никакого значения, но в случае агрегатных типов последний подход лучше, потому что в первом случае *delay не эквивалентен delayp, и приведение потребуется для используйте их взаимозаменяемо.

Но, как уже упоминали другие, вам лучше уйти с delay.

...