4

A user posted an answer which says:

So, take the Hash by reference

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

Also,

  • string[] is not a type in C++
  • ...

The original function posted by the question asker looks like:

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

I'm aware that in Java, the syntax for declaring an array is:

int[] anArray;

whereas in C++ it is:

int anArray[someNumber];

I suspect this is what the answerer was referring to, but maybe they meant something else. So I consulted n3337:

formatting note: irrelevant stuff omitted, newlines added for readability

§ 8.3.4 [dcl.array]

1 In a declaration T D where D has the form

D1 [ constant-expressionopt ] attribute-specifier-seqopt

and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is an array type;

...

T is called the array element type;

...

If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero. The constant expression specifies the bound of (number of elements in) the array. If the value of the constant expression is N, the array has N elements numbered 0 to N-1, and the type of the identifier of D is “derived-declarator-type-list array of N T”.

...

Except as noted below, if the constant expression is omitted, the type of the identifier of D is “derived-declarator-type-list array of unknown bound of T”, an incomplete object type. The type “derived-declarator-type-list array of N T” is a different type from the type “derived-declarator-type-list array of unknown bound of T”, see 3.9.

...

So anArray should be an array of someNumber int. And topA is adjusted to be pointer to std::string. Where does my understanding fail?


In order to avoid invalidating the current answers, I'll post this as an update. Some of you seem to be misunderstanding the nature of my question. I'm not asking about Java vs C++ nor arrays vs pointers, but rather from a language lawyer's point of view why string[] would not be considered a type.

If we take a look at §3.9/6:

... The declared type of an array object might be an array of unknown size and therefore be incomplete at one point in a translation unit and complete later on; the array types at those two points (“array of unknown bound of T” and “array of N T”) are different types. ... [ Example:

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

So arr clearly has a type.

Community
  • 1
  • 1

5 Answers5

4

Your understanding seems to be mostly correct--since topA is a formal parameter, its type is adjusted from array of T to pointer to T. Likewise, anArray would be an array of someNumber ints.

For what it's worth, there are limited circumstances under which you can have empty brackets in C++ and still have an array, not a pointer. The most common would be an extern declaration like:

extern int anArray[];

...which declares anArray to be an array of ints, the number of which is specified where it is defined.

If somebody starts with a parameter declared as: string topA[], it's true that the compiler will adjust that to string *topA, but in most cases, you probably want to change that to: std::vector<std::string> &topA (or std::vector<std::string> const &topA, if you're not going to modify the content of the array).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
4

string[] is an incomplete array type.

An incomplete array type can be completed:

C++11 §3.9/6:
The declared type of an array object might be an array of unknown size and therefore be incomplete at one point in a translation unit and complete later on; the array types at those two points (“array of unknown bound of T” and “array of N T”) are different types.

Usually this happens with a declaration like

extern int x[];

in some header, and then in an implementation file,

int x[42];

In addition to being incomplete due to unknown length, an array type can be incomplete due to an incomplete item type.

struct Blah;
extern Blah x[42];

auto main() -> int {}

This does not, however, allow an array of void.


In passing, it's worth noting e.g. unique_ptr<T> is different from unique_ptr<T[]>. The latter is restricted in the conversions it supports. Which is because if you convert a pointer to an array of type T, to pointer to array of type T_base or T_derived, then e.g. the item size can be different, foiling the indexing (and much else).

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
2

If you keep going through §8.3.4, we get this paragraph (bold emphasis mine):

An object of array type contains a contiguously allocated non-empty set of N subobjects of type T. The typederived-declarator-type-list array of N T” is a different type from the typederived-declarator-type-list array of unknown bound of T”, see 3.9. Any type of the form “cv-qualifier-seq array of N T” is adjusted to “array of N cv-qualifier-seq T”, and similarly for “array of unknown bound of T” and “array of runtime bound of T”. The optional attribute-specifier-seq appertains to the array.

With example:

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

Since the standard mentions array type, and shows an example clearly indicating that the type of a variable is an array, I think that's sufficient evidence that an array, in general, is a type. It's a weird type that doesn't play as nicely as the other fundamental types, but it's a type nevertheless. And that paragraph specifically mentions the type "unknown bound of T", which would be your string[] too.

Barry
  • 286,269
  • 29
  • 621
  • 977
2
extern int arr[]; // the type of array is incomplete

So arr clearly has a type.

arr has a type. That doesn't make int[] a complete type. arr has incomplete type until the array dimension is defined as well (potentially in another TU).

[...] type of the identifier of D is “derived-declarator-type-list array of unknown bound of T”, an incomplete object type

Referring to the concrete type of arr before that time (e.g. with sizeof) would be an error.

sehe
  • 374,641
  • 47
  • 450
  • 633
0

string[] is sort of a type, but it's a misleading one; you can't just copy string[]s around and expect it to do what you want. It's essentially another way of writing string *.

If you want an array of strings that you can pass around, use std::vector<std::string> (by value) or boost::shared_array<std::string> (by reference) or similar. boost::shared_array will probably act closest to what you're expecting from a Java array type.

fluffy
  • 5,212
  • 2
  • 37
  • 67