如果一个函数通过引用返回一个数组,它是指针的衰减吗?

时间:2018-03-16 10:50:04

标签: c++ c++98 cpp-core-guidelines

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

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

ComputeSomething()的返回行上,静态分析工具警告说有一个指针衰减的数组。我假设意图是改变它以使衰变显式(类似&(computed_values[0])),但那样就会破坏通过引用返回数组的点。

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

(假设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;
}

3 个答案:

答案 0 :(得分:0)

对于以下方法:

float (&ComputeSomething())[num_of_elems_calculated]{

    static float computed_values[num_of_elems_calculated];

    // do something...

    return computed_values;
}

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

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

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

感谢@Galik对此的投入。

答案 1 :(得分:-2)

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

因此ComputeSomething函数可以简化为

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

要“保留”大小信息,然后为了能够像现在一样使用该功能,调用者无论如何都需要知道。它不是自动转移的东西。所以使用指针不会有太大变化,除非你绝对想在数组上使用sizeof,但是这可以通过使用你必须在变量声明中提供的大小来回避。使用指针肯定会简化语法,因此也使代码更具可读性和可维护性。

您还可以使用内置大小信息的std::vector。或者强制升级到更现代的编译器,它可以使用C ++ 11,然后使用std::array,如果你想拥有编译时固定大小的数组。

我不确定C ++ 98中是否存在std::pair,或者它是否存在于C ++ 03中,但作为某种中间层,您可以使用std::pair<float*, size_t>返回指针的大小。

最后,您总是可以使用typedef为数组类型创建别名。然后你不需要在任何地方明确指定大小,它将简化语法:

typedef computed_values_type[num_of_elems_calculated];

....

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

...

computed_values_type& computed_values = ComputeSomething(...);

答案 2 :(得分:-4)

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