我编写了以下代码:
#include <iostream>
using namespace std;
const int * myFunction()
{
int * p = new int(5);
return p;
}
int main()
{
int * q = myFunction();
cout << "*q=" << *q;
cout << endl;
return 0;
}
我故意编写以上代码以接收错误。我犯的错误是我将函数myFunction()
的返回类型表示为const int *
,但是当我在myFunction()
中调用main()
时,指针变量q
却没有声明为const
。 myFunction()
的返回类型必须与将要接收其返回值的变量类型完全匹配(我在这里正确吗?这是我所了解的)。
因此,我通过将第11行更正为const int * q = myFunction();
来解决了该错误。现在,(指针)变量q
的类型为const int *
,与返回类型myFunction()
完全匹配,并且编译的代码没有错误,产生的输出为*q=5
(到目前为止,我的理解是正确的吗?)。
然后,我编写了以下代码:
#include <iostream>
using namespace std;
const int * const myFunction()
{
int * p = new int(5);
cout << "p: " << p;
return p;
}
int main()
{
int a;
const int * q = myFunction();
cout << "\nq=" << q;
cout << "\n*q=" << *q;
delete q;
q = &a;
cout << "\nq: " << q;
cout << endl;
return 0;
}
我也期望在这里出现错误。因为现在myFunction()
的返回类型为const int * const
,但是(指针)变量q
的类型为const int *
。 q
未声明为常量指针。但是程序已编译,我得到的输出如下:
p: 0x36cb8 q=0x36cb8 *q=5 q: 0x61ff08
我很困惑第二个代码为什么要编译和运行。我以为是谁将从myFunction()
那里获得返回值,应该总是照顾它(即不能允许它使用不同的内存地址),但是指针变量q
却采用了不同的方法内存位置。
答案 0 :(得分:3)
myFunction的返回类型必须与要接收其返回值的变量类型完全匹配。 (我在这里正确吗?这是我所了解的。)
否,返回类型必须与变量类型不完全匹配。但是必须可以将返回类型隐式转换为变量的类型。 例如,将编译如下内容:
int someInt = getMeAFloat();
如果getMeAFloat
返回float
,则会编译该文件,因为可以将float
隐式转换为int
。 (请注意,这会给您一个警告,并且是不好的,因为您会丢失float
的额外信息,但是我只是想说明我的观点)
您的第一个示例无法编译,因为通常无法将const int*
转换为int*
。
正如user4581301所指出的,第二个示例中的第二个const
无关紧要,因为只有返回的指针值被分配给了主函数中的指针。第二个const
使指针本身恒定,这对值没有影响。
这意味着const int * const myFunction()
等于const int * myFunction()
答案 1 :(得分:2)
在第二个代码中,q
是const int *
-非常量“指向const int
的指针”。由于q
本身不是const
,因此可以重新分配它以指向新地址。
编译器允许q = &a;
,因为可以将{{1}分配给{{1}(即int*
是&a
以来返回的a
) }}。换句话说,可以将“指向非const数据的指针”分配给“指向const数据的指针”,从而有效地对以其他方式可写的数据进行只读访问。
反之则不成立-无法将“指向const数据的指针”分配给“指向非const数据的指针”,因为这将允许对只读数据进行可写访问-这就是为什么第一个代码无法执行编译。