64,683
社区成员
发帖
与我相关
我的任务
分享
int ival = 1024;
int* pival = &ival;
int*& sdf = pival; //正确
const int*& pi_ref = pival;//错误,为什么
const int* const& pi_ref = pival;//正确
error: invalid initialization of reference of type 'const int*&' from expression of type 'int*'
int main()
{
int i=0;
// T => T &
int* p=&i;
int& r=i;
// T => T const
int const ic=i;
// T* => T const *
int const * pic=p;
// T* => T * const
int * const cpi=p;
// T* => T const * const
int const * const cpci=p;
// T => T const &
int const& rci=i;
// T& => T const &
int const& rci2=r;
return 0;
}
2)二维指针和指针的引用
从右往左看,=>表示可以转化,!=>表示不能转化
T** => T * const * => T const * const *
T*& => T * const & => T const * const &
T* => T * const & => T const * const &
T** !=> T const **
T*& !=> T const *&
证明:
typedef P T*;
因为:T* => T const * 和 T& => T const &
P* => P const * 即:T** => T * const *
P& => P const & 即:T*& => T * const &
又因为:T => T const 或 T* => T const *
T * const * => T const * const *
T * const & => T const * const &
测试代码:
int main()
{
int i=0;
int* p=&i;
int** pp=&p;
int*& rp=p;
// T** => T * const *
int * const * pcpi=pp;
// T** => T const * const *
int const * const * pcpci=pp;
// T*& => T * const &
int * const & rcpi=rp;
// T*& => T const * const &
int const * const & rcpci=rp;
// error C2440: 'initializing' : cannot convert from 'int **' to 'const int **'
int const ** ppci=pp;
// error C2440: 'initializing' : cannot convert from 'int *' to 'const int *&'
int const *& rpci=rp;
return 0;
}
int *p;
const int *&r = p; // reference to a pointer to const int
const int immutable = 0;
r = &immutable; // assign p to address of immutable
*p = 1; // whoops, now 0 = 1!
如果把r定义成const int * const& r,那么r就是一个const 引用,它用p初始化后就不能再用其他变量对他赋值,就是说此时r=&immutable这句代码就会出错?是这样吗
另外,C++primer51页说const引用就是指向const对象的引用,const int*&r不是一个const引用,是因为r引用的指针不是const指针,比如定义
const int*p;//这个不是const指针,虽然指向的是const对象
const int* const p1;//这个才是const指针
是这样吗
int a;
int * const p = &a;
int * const & r1 = p;
int ( * const ( & r2 ) ) = p;
const int a;
const int * p = a;
const int * & r = p;
//它相当于:
int const ( * ( & r ) ) = p;
//r 是一个引用,它引用的是一个指针,指针指向一个int const变量。
//用typedef 来解释它就是:
typedef int const cint;
typedef cint * pcint;
typedef pcint & rpcint;
rpcint r = p;
[/quote]
你把我的 (int*) const&换成了 ((int const)*)&
int & r0 = 20.0; //失败
const int & r1 = 20.0; //成功
const int a;
const int * p = a;
const int * & r = p;
//它相当于:
int const ( * ( & r ) ) = p;
//r 是一个引用,它引用的是一个指针,指针指向一个int const变量。
//用typedef 来解释它就是:
typedef int const cint;
typedef cint * pcint;
typedef pcint & rpcint;
rpcint r = p;
int main()
{
int a = 0;
int* p = &a;
typedef int* IP;
IP const& rp = p;
return 0;
}
const int* const& pi_ref = pival;//正确
这里要注意,pi_ref引用的并不是pival,而是由它隐式转换而来的int const *,从语法逻辑上讲,这里应该产生一个类型为int const *的临时对象,pi_ref引用这个对象。为了保证pi_ref的有效性,这个本应在这条语句结束后就释放的临时对象生命期被延长到与pi_ref相同。
如果输出pi_ref的地址和pival的地址,你会发现它们是不同的。
不过,这只是逻辑上的概念,或许某个编译器会把pival和临时对象优化为同一个,毕竟pi_ref是个const reference,这就代表着它是只读的。尽管编译器这样做是错误的,但我们也不能期待它永远守规矩,我们所能做的就是自己要守规矩,不要去const_cast。
int * a;
int const * b;
int const ** c = &a;//假如这一步允许的话
*c = b; //现在a就等于b,我们成功地把一个int const *赋值给了一个int**,没有任何另人警惕的强制类型转换。
上面两个赋值,后面那个肯定不能禁止 ,否则会让指针失去存在意义,所以第一个赋值被禁止,T **不允许隐式转换为T const **
第三个(我列出来的,不是楼主的代码):
typedef P = T*;
T**就是P*, T*const *就是P const *,又回到了第一条。
最后再看楼主的最后一行代码:
const int* const& pi_ref = pival;//正确
pival类型是int*,pi_ref类型比较复杂,我们可以定义一下:
typedef int* PInt;
typedef int const * PCInt;
PInt可以 隐式转换为PCInt;
pi_ref是PCInt const &
pival是PInt,可以隐式转换为PCInt。
现在清楚了,为了支持函数参数中用const reference代替值拷贝,C++允许 对象A隐式转换为B的传给B const &类型。这里有一个隐式类型转换,由pival转换为PCInt然后赋值给PCInt const &类型的pi_ref
注意,const是左结合 的它修饰的是它左边的类型,当它在最左时才修饰右边,所以const int与int const是等价的。我一般为了清晰,都写后一种。
此外,我现在的系统很慢,输入法的响应远跟不上我输入的速度,所以会有多空格 、少字、少标点的情况 请大家谅解。
int a = 0;
const int *cpa = &a; //正确
int *pa = &a;
const int **cppa = &pa; //错误