为什么数组元素的地址有时会被误认为是声明?

时间:2013-04-26 01:49:05

标签: c++ arrays reference most-vexing-parse

我有一些用户定义的迭代器,偶尔我会得到一个很容易解决的奇怪错误,但我不明白为什么我会得到它:

uint8_t bytes[pitch*height];

array_iterator::col_iterator a( &bytes[0] );

array_iterator::row_iterator base_iter_begin(
  array_iterator::col_iterator( &bytes[0] ), width, pitch );

array_iterator::row_iterator base_iter_end(
  array_iterator::col_iterator( &bytes[pitch*height] ), width, pitch
  );

我有一个名为array_iterator的类,其中嵌入了typedefs row_iterator和col_iterator。 row_iterator构造函数将col_iterator作为其第一个参数。第一个和最后一个语句工作正常。中间语句无法编译,并出现以下错误:

test-2d-iterators.cc:780: error: declaration of 'bytes' as array of references

写入&(bytes [0])无法解决问题(不出所料,因为[]的优先级高于&)。当然,我可以用“a”代替显式col_iterator构造函数调用,但为什么我必须这样做?如果出现问题,为什么最后一行中的col_iterator构造函数会编译?

感谢。

1 个答案:

答案 0 :(得分:2)

首先,我们可以将您的问题缩小到以下几行:

struct row_iterator { ... };
typedef unsigned* col_iterator;
unsigned bytes[5];
row_iterator base_iter_begin(col_iterator(&bytes[0]));

第三行被理解为:

row_iterator base_iter_begin(col_iterator& bytes[0]);

并且该行声明了一个函数,该函数将0作为参数引用到col_iterator并返回一个int。确实是most vexing parse的案例,如评论中所指出的那样。

摆脱它的最简单方法是使用复制初始化而不是直接初始化(在C ++中初始化):

row_iterator base_iter_begin = row_iterator(col_iterator(&bytes[0]));

在你的情况下会是:

array_iterator::row_iterator base_iter_begin = array_iterator::row_iterator(array_iterator::col_iterator( &bytes[0] ), width, pitch );

注意:如果您使用的是C ++ 11,则有even more initialization rules,您可以使用列表初始化来删除样板文件和最令人烦恼的解析:

array_iterator::row_iterator base_iter_begin{array_iterator::col_iterator(&bytes[0]), width, pitch};