将函数返回的数组指针作为另一函数参数传递的报错问题
一、错误原因拆解
1. 保留重载时的匹配失败
你的SortElements函数第二个参数是非const左值引用(int*&/float*&),而ChooseElements返回的是临时指针对象(右值)。C++规则明确禁止:非const左值引用不能绑定到右值。
编译器尝试匹配SortElements(m, ChooseElements(X, n, m))时,找不到接受int*(右值)作为第二个参数的重载版本——你的两个SortElements都要求绑定到可修改的左值指针,因此直接报错“没有匹配的重载函数”。
2. 仅保留INT版本时的左值错误
这是上述规则的直接体现:ChooseElements返回的临时指针是右值,无法作为非const引用参数的初始值。非const引用的设计目的是允许函数修改传入的变量,而临时右值无法被修改(也没有修改意义),所以编译器直接拒绝这种绑定。
拆分语句能正常运行,是因为Y是命名的左值变量,符合非const引用的绑定要求。
二、实现“函数作为参数”的解决方案
方案1:修改SortElements参数类型(最简单直接)
观察你的SortElements逻辑,它只修改指针指向的数组元素,并没有修改指针变量本身(比如未重新分配内存改变指针指向)。因此完全不需要将参数设计为指针的引用,改成普通指针传递即可:
int * SortElements(int m, int * Y) { for (int i = 1; i < m; i++) { for (int j = 0; j < m - i; j++) { if (Y[j] > Y[j + 1]) { int Temp = Y[j]; Y[j] = Y[j + 1]; Y[j + 1] = Temp; } } } return Y; } float * SortElements(int m, float * Y) { // 复制int版本逻辑,参数改为float* }
修改后,SortElements(m, ChooseElements(X, n, m))就能正常编译——临时指针(右值)可直接传递给值传递的参数。
方案2:若必须保留指针引用(如未来需修改指针本身)
如果后续SortElements需要修改指针变量(比如重新分配内存),必须保留引用参数,可使用std::move将右值转换为可绑定的右值引用(C++11及以上支持):
Y = SortElements(m, std::move(ChooseElements(X, n, m)));
但这种方式需要将SortElements的参数改为int*&&(右值引用),或同时提供左值、右值引用的重载,会增加代码复杂度,非必要不推荐。
方案3:用模板消除重复代码(更优雅)
你的ChooseElements和SortElements都是重复的类型逻辑,用模板可大幅减少冗余,还能天然支持更多类型:
#include <algorithm> // 用于std::swap、std::copy template<typename T> T* ChooseElements(T* X, int n, int& m) { T* Y = nullptr; m = 0; for (int i = 0; i < n; i++) { if (X[i] > 0) { // 先统计数量再一次性分配会更高效,这里保留原逻辑的修改方式 T* temp = new T[m + 1]; if (Y != nullptr) { std::copy(Y, Y + m, temp); delete[] Y; } temp[m] = X[i]; Y = temp; m++; } } return Y; } template<typename T> T* SortElements(int m, T* Y) { for (int i = 1; i < m; i++) { for (int j = 0; j < m - i; j++) { if (Y[j] > Y[j + 1]) { std::swap(Y[j], Y[j + 1]); } } } return Y; }
使用模板后,代码量大幅减少,调用方式不变,且SortElements(m, ChooseElements(X, n, m))可正常编译。
额外提示:new与realloc混用问题
原代码同时用new分配内存、realloc重新分配是未定义行为!realloc仅能用于malloc/calloc分配的内存,建议统一使用new+delete[]或malloc+realloc+free,方案3中已修正为new的安全用法。
内容的提问来源于stack exchange,提问作者BEEET Hvcw

