如果一个函数 returns 一个引用数组,它是指针的衰减吗?

If a function returns an array by reference is it a decay to pointer?

在下面的示例代码中,ComputeSomething() return是对数组的引用。

我被要求使用 C++ 核心指南(MSVC 工具链上的 NuGet 包)作为额外的静态分析工具。

ComputeSomething() 的 return 行,静态分析工具警告说有一个指针衰减数组。我假设意图是更改它以使衰减明确(类似于 &(computed_values[0])),但这将破坏 return 通过引用数组的意义。

对于return引用数组的这个特定用例,这是一个有效的警告还是噪音?

(假定 C++98 约束)

float (&ComputeSomething( const seed_t(&seed_data)[num_of_elems_seeded] ))[num_of_elems_calculated]{

    static float computed_values[num_of_elems_calculated];

    // do something...

    return computed_values;
}

是的。

ComputeSomething函数中,computed_values是一个数组。和往常一样,它可以自然地衰减到指向其第一个元素的指针。

所以ComputeSomething函数可以简化为

const float* ComputeSomething(...){ ... }

到 "preserve" 大小信息,然后才能像现在一样使用函数,调用者需要知道大小 anyway。它不是自动转移的东西。所以使用指针不会有太大变化,除非你绝对想在数组上使用 sizeof ,但是可以通过使用你必须在变量声明中提供的大小来回避。使用指针肯定会简化语法,因此也会使代码更具可读性和可维护性。

您也可以使用 std::vector,它内置了尺寸信息。或者强制升级到可以使用 C++11 的更现代的编译器,然后使用 std::array 如果你想要 compile-time fixed-size 数组。

我不确定 std::pair 是否存在于 C++98 中,或者它是否出现在 C++03 中,但是作为某种 middle-ground 你可以使用 std::pair<float*, size_t> 到 return 指针 大小。

最后,您始终可以使用 typedef 为您的数组类型创建别名。那么就不用到处显式指定size了,语法会简化不少:

typedef computed_values_type[num_of_elems_calculated];

....

computed_values_type& ComputeSomething(...) { ... }

...

computed_values_type& computed_values = ComputeSomething(...);

从编译的二进制文件的角度来看,对数组的引用只是指向第一个元素的旧指针。它与原始指针的区别仅在于类型本身,后者包含有关数组大小的信息。例如,它可以用于 compile-time 大小检查、编译器警告或 range-based for 循环

对于以下方法:

float (&ComputeSomething())[num_of_elems_calculated]{

    static float computed_values[num_of_elems_calculated];

    // do something...

    return computed_values;
}

与静态分析工具中可能发生的情况不同,指针衰减的潜在数组不是在方法内部确定的,而是在调用者调用函数时确定的:

// expected to decay
float *some_computation = ComputeSomething(); 

// not expected to decay to pointer
float (&safer_computation)[num_of_elems_calculated] = ComputeSomething();

感谢@Galik 对此的贡献。