通过引用调用数组

时间:2010-09-08 17:23:23

标签: c++ arrays

我想做的是这样的事情:

void dosth(bool& a) {
  a[2] = false;
}

int main() {
  bool a[10];

  dosth(a);

  return 0;
}

我想通过引用调用,数组作为参数。怎么实现这个?

THX

5 个答案:

答案 0 :(得分:8)

像这样:

typedef bool array_type[10];

void dosth(array_type& a)
{
    a[2] = false;
}

int main()
{
    array_type a;
    dosth(a);
}

或没有typedef:

void dosth(bool (&a)[10])
{
    a[2] = false;
}

int main()
{
    bool a[10];
    dosth(a);
}

或更一般地说:

template <size_t Size>
void dosth(bool (&a)[Size])
{
    /*static_*/assert(Size > 2);

    a[2] = false;
}

int main()
{
    bool a[10];
    dosth(a);
}

如果你不在C ++ 0x中,你可以像这样实现一个(简单)static_assert

template <bool>
struct static_assert_type;

template <> // only true is defined
struct static_assert_type<true> {}

#define static_assert(x) { static_assert_type<(x)>(); }

如果数组大小太小,可以取消注释static_assert并获得编译时错误。

答案 1 :(得分:5)

您可以允许数组衰减为指针,如Philippe的答案。

是一种更加类型安全的解决方案,它只接受数组并允许编译时范围检查
template <size_t SIZE>
void dosth(bool (&a)[SIZE])
{
    a[2] = false;
}

如果编译器不支持static_assert(SIZE > 2);,您可以添加BOOST_STATIC_ASSERT(SIZE > 2);(或static_assert),如果索引超出范围,则会产生编译错误。

答案 2 :(得分:2)

这有点棘手,简单的方法(以及C中唯一可用的方法)是将函数的签名定义为获取指针:

void dosth( bool* a );

数组将自动衰减成为指向第一个元素的指针,只要你足够小心,它就会起作用。请注意,void dosth( bool a[10] )正好是上面的签名:编译器会为您翻译它。

由于几个原因,这是不安全的,首先是它允许调用者传递任何大小的数组,甚至根本不传递数组(dosth(0);)。

通过使用引用,可以在C ++中使用typeafe:

void dosth( bool (&a)[ 10 ] );

现在,编译器将确保将正好10个bool的数组传递给函数。这里有一些含义,首先是不仅用户不能传递空指针,而且她只能传递一个包含10个元素的数组,因此在以后访问第三个元素时不必担心溢出on(a[2]=false;)。

另一方面,它限制了可用性,因为用户无法传递超过10个元素的数组,也无法传递动态分配的数组(new bool[10])。这可以通过使用模板来改进:

template <std::size_t N>
void dosth( bool (&a)[N] ) {
   static_assert( N >= 10 );
   //...
}
编辑:我打算回复塞德里克的评论,但这可能太长了。你是对的,它使动态分配的问题得不到解决。正如@GMan所说,在一般情况下,您希望使用其他数据类型来处理动态分配的内存。无论如何,有一种复杂的方法可以使用new[]分配的内存来实现它,它不是那么直接。

问题是类型必须是bool [10],但new T[n]会返回T*而不是T[n]。提供typedef也无济于事:

typedef bool b10[10];
b10* p = new b10;    // error cannot convert from int* to int (*)[10]

您可以通过不请求单个数组而不是数组数组来克服该限制:

bool (*array)[10] = new bool[1][10];
dosth(*array);

但当然您需要使用delete []而不是delete

delete [] array;

答案 3 :(得分:0)

如果要引用数组,可以执行以下操作。请注意,dosth只接受对该大小的数组的引用,并且您将无法提供堆分配的数组(即bool* c = new bool[10])。

void dosth(bool (&a)[10]) {
         a[2] = false;
}

int main() {
        bool a[10];
        bool (&aa)[10] = a;
        dosth(a);

        return 0;
}

答案 4 :(得分:-2)

您必须将参数声明为指针:

void dosth(bool* a) {
  a[2] = false;
}

数组与指针

基本相同