1.引用返回左值问题
int &get(int *array, int index){return arry[index];}
int main()
{
int ia[10];
for (int i = 0; i != 10; ++i)
{
get(ia, i) = i;
}
}
这段代码摘自C++primer 第五版 课后习题 exercise 6.32
书上也明确说
“函数的返回类型决定函数调用是否是左值。调用一个返回引用的函数得到左值,其他返回类型得到右值”
也就是说因为函数类型是引用类型,所以返回的是左值,所以get(ia, i)
是一个左值,所以i才能给get(ia, i)
赋值,如果函数声明成int get(int *array, int index){return arry[index];}
因为函数不是引用类型,返回的是右值,所以不能被赋值,我这样理解没错吧?(可能我描述中有概念弄错,请指出,我感觉我那句“get(ia, i)
是一个左值”好像有点概念上描述的错误)
希望大神在给我指导一下!谢谢啦!
2.
int odd[] = { 1, 3, 5, 7, 9 };
int even[] = { 0, 2, 4, 6, 8 };
decltype(odd) *arrPtr(int i)
{
return (i % 2) ? &odd : &even;
}
以上代码摘自C++primer第五版6.3.3节内容
疑问是为何返回的是&odd(&even)而不是odd(even),数组名不是可以自动变成指向数组首元素的指针吗?
下面说一下我的理解,不知道对错?求指导!
先举个例子:
int a[2] = { 2, 4 };
int *p1 = a;
decltype(a) *p2 = &a;
int *p1 = a;
这里数组名a自动变成指向数组首元素的指针,这里的指针针对的是数组的某个元素,而decltype(a)
获得是数组类型,加上*
表示指向含有2个整数的数组的指针,这里的指针是指向数组整体的,而非单个元素,所以需要&a
,但是&a
的结果不也是数组首元素的地址吗?为何非要写成这种形式呢?直接decltype(a) * p2 = a;
是错误的。
然后我又测试了一下输出
代码如下:
cout << *p1 << endl;//2
cout << *(*p2 + 1) << endl;//4
发现p2竟然是个指向指针的指针,貌似是证明了我的猜想,p2是指向数组整体的,要想访问数组元素,需要两次解引用,这也是为什么decltype(a) *p2 = &a;
而不是decltype(a) * p2 = a;
?
不知道自己说的对不对,即使对的话,总感觉自己好差点什么东西没理解,希望大神指导一下,给我一种豁然开朗的感觉!
然后我又测试了一下这个问题,代码如下:
cout << p1 << endl;//00488860
cout << *p2 + 1 << endl;//00488864
cout << p2 << endl;//00488860
cout << &a << endl;//00488860
cout << &a + 1 << endl;//00488868
*p2 + 1
只是向前移动一位元素,但是为何&a + 1
直接跳过整个数组呢?(我还测试数组元素是三个的情况,发现是加12)
以上,写的逻辑很乱,因为很多东西都是我在提问的时候突然想到,然后又在编译器中调试,然后加上来提问的,希望见谅!
给出数组:
说来说去其实就仨类型,先给你摆出来:
看来
decltype(a)
的类型不用多说,正如 @Windoze 所回答的,在这里是type1
类型。那么你列举的
decltype(a) * p2 = a;
就相当于type2 p2 = a;
即:等号左边是
int(*)[2]
,等号右边是int[2]
,这显然不能画等号。再看你列举的这个
*(*p2 + 1)
是什么鬼:decltype(a) * p2
<==>type1 *p2
所以
*p2
类型就是type1
,a
的类型呢?也是type1
,若有decltype(a) * p2 = &a;
则*p2
就是a
.故:
*(*p2 + 1)
<==>*(a + 1)
<==>a[1]
<==>4
没啥问题吧?
最后说说你那一大堆测试:
画图解释:
刚才说了,
a
的类型是int[2]
,那么&a
的类型就是int(&)[2]
(也就是我留着没说的type3
)。而int *p = a;
,这个p
的类型是int*
。而*p2 + 1
<==>a + 1
<==>p + 1
。三种类型如上图所示范围。骐骥一跃,相当于驽马“两”驾啊。
综上所述,你可能混淆了
type1
、type2
、type3
三种类型的区别。区分开,其实非常简单。