通过复制将数组地址传递给匿名函数失败

Fail to pass array address by copy to anonymous function

本文关键字:函数 失败 址传 复制 数组 地址      更新时间:2023-10-16
void F(int A[], int n) { // Correct
    int arr[3] = {0}; // A[..] in the range of 0-2
    for_each(A, A+n, [&arr](const int& num) -> void {
       ++arr[num];
    });
}
void F(int A[], int n) { // Wrong: b/c [arr] should be [&arr]
    int arr[3] = {0}; // A[..] in the range of 0-2
    for_each(A, A+n, [arr](const int& num) -> void {
       ++arr[num];
    });
}

错误:只读位置' arr[((int)num)] ' ++arr[num];

问题>为什么我看到上面的错误?如果匿名函数需要修改该值,则需要在[]的参数前加上&。然而,在这里,我传入一个数组的地址。为什么我仍然要用[&arr]而不是[arr]

谢谢

数组不是指针。arr不是指针,它是一个数组。标准中没有任何地方说在lambda捕获时发生数组到指针的转换。所以不是捕获指针,而是捕获实际的数组,通过值或引用。由于按值捕获实际上是const,除非lambda声明为mutable,否则您将得到错误。

换句话说,在[&arr]的情况下,lambda的闭包类型将具有该数据成员:

int (&arr)[3];

这个数据成员在[arr]的情况下:

int arr[3];

不要忘记,当lambda声明没有mutable时,闭包的operator()const成员函数:

auto operator() (const int& num) const -> void {
  // ... code
}

这意味着它不能修改由value捕获的数据成员。

lambda将arr捕获为const。如果你希望能够修改数组,你需要使用mutable:

void F(int A[], int n) { // Wrong: b/c [arr] should be [&arr]
    int arr[3] = {0}; // A[..] in the range of 0-2
    for_each(A, A+n,  [arr](const int& num) mutable -> void {
       ++arr[num];
    });
}
或者,更准确地说,lambda表达式就像一个没有可变的关键字的const函数:

5.1.2.5 lambda表达式的闭包类型有一个公共内联函数调用操作符(13.5.4),其形参和返回类型为由lambda表达式的参数声明子句和描述trailing-return-type分别。这个函数调用操作符是声明const(9.3.1)当且仅当lambda表达式为参数声明子句后面没有mutable