C++错误:"taking address of temporary array"

C++ error: "taking address of temporary array"

本文关键字:of temporary array address taking 错误 C++      更新时间:2023-10-16

我正试图在if语句中声明一个数组。我是这样写代码的,这样一旦if块退出,对象就会留在作用域中,但现在我有了一个新问题:"获取临时数组的地址"。我如何用另一种方式重写它,以便为maskArray分配正确的值?

int* maskArray;
if(conditional==true)
   maskArray = (int[9]) {0,1,0,1,-4,1,0,1,0};

假设您以后不会修改maskArray指向的内容,那么最好/最简单的解决方案是:

const int* maskArray;
if(conditional==true)
{
     static const int myArray[9] = {0,1,0,1,-4,1,0,1,0};
     maskArray = &myArray[0];
}

如果您从未计划更新数组,静态常量会起作用,但如果您要更新它,则需要一个单独的副本。这可以在堆栈上创建,也可以在堆上创建。在堆栈上创建:

int* maskArray;
int myArray[9] = {0,1,0,1,-4,1,0,1,0};
if(conditional==true)
{
     maskArray = &myArray[0];
}
// when `myArray` goes out of scope, the pointer stored in maskArray will be useless! If a longer lifetime is needed, use the heap (see below).

要在堆上动态创建数组的新副本,需要使用new[]分配内存。这样做的好处是,在你决定删除它之前,只要它有用,它就可以一直存在

int* maskArray;
if(conditional==true)
{
     maskArray = new int[9] {0,1,0,1,-4,1,0,1,0};
}

记住删除是以后使用delete[] maskArray

虽然原始构造在C++中确实无效,但标准C++确实有一个相当相似的功能:可以使用显式类型名称和列表初始值设定项创建临时数组

using I9 = int [9];
I9{ 0, 1, 0, 1, -4, 1, 0, 1, 0 };

以上是临时数组对象的有效C++语法。但是,如果您尝试在GCC中使用它,您会很快发现GCC拒绝将数组到指针的转换应用于此类临时数组,例如

using C10 = char [10];
C10 str;
std::strcpy(str, C10{ 'a', 'b', 'c' });
// GCC: error: taking address of temporary array

上面的内容是非常有效的C++,但是GCC中的一个错误阻止了它的编译。Clang和MSVC接受此代码。

在您的原始代码中,您实际上依赖于GCC扩展,该扩展允许您在C++代码中使用C样式复合文字语法,但该扩展显然也遇到了与上述相同的错误。

(int[9]) {0,1,0,1,-4,1,0,1,0}创建一个临时数组,该数组将在完整语句完成后立即销毁。(注意,从技术上讲,这不是C++,而是编译器支持的C99功能,作为C++的扩展。(

maskArray = (int[9]) {0,1,0,1,-4,1,0,1,0};获取该临时数组,将其转换为指针,并将该指针存储在maskArray中。一旦此语句完成,临时数组将被销毁,maskArray中的值将不再有效。

使用这样一个临时数组的唯一方法是在同一条语句中使用它,例如将它传递给将使用它的函数:

void foo(int (&arr)[9]);
foo((int[9]) {0,1,0,1,-4,1,0,1,0});

这是可以的,因为即使临时数组被销毁,它也只是在函数返回并且没有任何东西使用数组之后才被销毁。(函数最好不要以某种方式将长期引用或指针存储到数组中,但这与正常情况没有什么不同。(

只有在声明数组时才能对其进行初始化。因此,如果需要在循环中确定其范围,请在循环中声明一个数组:

int* maskArray;
if (conditional == true) {
    int locArray[] = {0,1,0,1,-4,1,0,1,0};
    maskArray = locArray;
    // ...
} // locArray goes out of scope here
// BEWARE : maskArray is now a dangling pointer (maskArray = NULL is safer)

正如M.M所注意到的,您可以通过在块内声明悬挂的maskArray来避免它(如果您可以直接使用locArray,则可以省略它(:

if (conditional==true) {
    int locArray[] = {0,1,0,1,-4,1,0,1,0};
    int *maskArray = locArray; // may be fully omitted if locArray is enough
}

您可以使用临时数组来实现此

int temp [] = {0,1,0,1,-4,1,0,1,0};
size_t n = sizeof(temp)/sizeof(int);
if (condition == true )
{
   maskArray = new int[n]{0,1,0,1,-4,1,0,1,0};
}
// ...
delete [] maskArray; // Free memory after use

或者简单地使用std::vector

std::vector<int> maskArray;
if( condition == true )
{
  maskArray = {0,1,0,1,-4,1,0,1,0}; // C++11 initializer_list vector assignment
}
if (...)
{
  static int a[9] = { ... };
  maskArray = a;
}