2014-11-25 6 views
4

Пользователь разместил answer, который говорит:Является ли строка [] не типом?

Итак, возьмите Hash по ссылке

void topWords(Hash const& t, std::string const& word, std::string* topA); 

Кроме того,

  • string[] не тип в C++
  • .. .

оригинальная функция отправленная на вопрос спрашивающим выглядит следующим образом:

void topWords(Hash t, string word, string topA[]); 

Я знаю, что в Java, синтаксис для объявления массива является:

int[] anArray; 

, тогда как в C++ это это:

int anArray[someNumber]; 

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

форматирования примечание: не имеет значения материал опущена, добавлены новые строки для удобства чтения

§ 8.3.4 [dcl.array]

1 В декларации T D где D имеет форма

D1 [постоянное выражение неавтоматического] атрибут-спецификатор-сл неавтоматического

и тип идентификатора объявления T D1 является «производного описатель-типа списокT», то тип идентификатор от D - тип массива;

...

T называется массив элемент типа;

...

Если константа-выражение (5.19) присутствует, то он должен быть интеграл постоянным выражением и его значение должно быть больше нуля. Константное выражение указывает границу (количество элементов in) массив.Если значение константы выражения N, то массива имеет N элементов пронумерованных 0 к N-1, и типу идентификатора D является «производного описателем типа списку массив из N T».

...

За исключением случаев, указанных ниже, если константа опущен, тип из идентификатора D является «производного описатель-типа список массив неизвестную грань T» , неполный тип объекта. Тип «производного описателя-тип список массива N T» другой тип от типа «производного описателя-типа список массива неизвестного связанного из T», см 3.9.

...

Так anArray должен быть массивом someNumber int. И topA настроен на pointer to std::string. Где мое понимание терпит неудачу?


Во избежание аннулирования текущих ответов, я отправлю это как обновление. Некоторые из вас, похоже, неправильно понимают характер моего вопроса. Я не спрашиваю о Java vs C++ и массивах против указателей, но, скорее, с точки зрения адвоката языка, почему string[] не будет считаться типом.

Если мы посмотрим на §3.9/6:

... Заявленный тип объекта массива может быть массив неизвестного размера и, следовательно, быть неполными в одной точке в ЕП и завершить позже; типы массивов в этих двух точках («массив неизвестная граница T» и «массив N T») - это разные типы. ... [ Пример:

extern int arr[]; // the type of array is incomplete 

Так arrявно имеет тип.

+0

'std :: string' - это класс, а не тип. –

+13

@self Но ... §9/1: «Класс - это тип». –

+2

Классы тоже типы. 'std :: string' - это класс, а не примитив. Классы и примитивы, однако, являются обоими типами. –

ответ

0

string[] - это своего рода тип, но это вводит в заблуждение; вы не можете просто скопировать string[]s и ожидать, что он сделает то, что вы хотите. Это, по сути, еще один способ написания string *.

Если вы хотите получить массив string, который вы можете использовать, используйте std::vector<std::string> (по значению) или boost::shared_array<std::string> (по ссылке) или аналогичные. boost::shared_array, вероятно, будет действовать ближе всего к тому, что вы ожидаете от типа массива Java.

4

Ваше понимание похоже в основном правильное - поскольку topA является формальным параметром, его тип регулируется от array of T до pointer to T. Аналогично, anArray будет массивом someNumber ints.

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

extern int anArray[]; 

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

Если кто-то начинает с параметром, объявленным как: string topA[], это правда, что компилятор будет регулировать, что string *topA, но в большинстве случаев вы вероятно, хотят изменить что: std::vector<std::string> &topA (или std::vector<std::string> const &topA, если вы 'не собираюсь изменять содержимое массива).

2

Если продолжать идти через §8.3.4, мы получаем этот пункт (жирный курсив мой):

Объект типа массива содержит смежно выделенный непустое множество N подобъектов типа Т. типа «производного описатель-типа список массива NT» это другой типа от типа «производного описателя-типа списка массива из неизвестная граница T ", см. 3.9. Любой тип формы «cv-qualifier-seq массив NT» настроен на «массив из N cv-qualifier-seq T», а также для «массива неизвестной границы T» и «массива время выполнения T ". Необязательный атрибут-спецификатор-seq appertains к массиву.

С Например:

typedef int A[5], AA[2][3]; 
typedef const A CA; // type is “array of 5 const int” 

Поскольку стандарт упоминает тип массива, и показывает пример ясно показывая, что тип переменной является массивом, я считаю, что это достаточно доказательств, что массив, в общем , является типом. Это странный тип, который не играет так же хорошо, как другие фундаментальные типы, но, тем не менее, это тип. И в этом параграфе конкретно упоминается тип «неизвестной границы T», который также будет вашим string[].

4

string[] является неполным типом массива.

Неполный тип массива может быть завершена:

C++ 11 §3.9/6:
объявленный тип объекта массива может быть массив неизвестного размера и поэтому должны быть неполными в одной точке в единицах перевода и позднее; типы массивов в этих двух точках («массив неизвестной границы T» и «массив NT») - это разные типы.

Обычно это происходит с декларацией, как

extern int x[]; 

в какой-то заголовок, а затем в файле реализации,

int x[42]; 

В дополнение к неполной из-за неизвестной длины, массив тип может быть неполным из-за неполного типа товара.

struct Blah; 
extern Blah x[42]; 

auto main() -> int {} 

Это, однако, не позволяют массив void.


Проходя мимо, стоит отметить, например, unique_ptr<T> отличается от unique_ptr<T[]>. Последний ограничен в конверсиях, которые он поддерживает. Это связано с тем, что если вы конвертируете указатель в массив типа T, указатель на массив типа T_base или T_derived, то, например, размер элемента может быть другим, сдерживая индексирование (и многое другое).

2
extern int arr[]; // the type of array is incomplete 

Так обр, очевидно, имеет тип.

arr имеет тип. Это не делает int[] полным типом. arr имеет неполный тип, пока не будет определен размер массива (возможно, в другом TU).

[...] типа идентификатора D является «производным-описателем типа список массива неизвестного связанного Т», неполный типа объекта

Ссылаясь на бетон тип arr до этого времени (например, с sizeof) будет ошибкой.