- 1 NULL
#define NULL ((void *)0)
When
NULL
is assgined to a pointer, it means the pointer does not point to anything.
- 2 void*
void *pv;
A pointer to void is a general-purpose pointer used to hold references to any data type.
Constants and Pointers
1 pointers to a constant
初始代码:
int a = 2;
const int b = 4;
const int* pci;
pci = &b;
调试分析:
- pci可以改变自身的值,即指向另一个变量
pci = &a;
- *pci不允许改变指向的变量的值
*pci = 8; //error: assignment of read-only location ‘* pci’
pci可以指向一个int或一个const int
pci的下述定义是等价的
const int *pci;
int const *pci;
简单图
- 灰色表示不可通过指针的反引用改变变量的值
2 constant pointers to nonconstant
初始代码
int a = 2;
const int b = 4;
int c = 6;
int* const cpi = &a;
调试分析
- cpi必须在声明时就被初始化,否则会有如下报错
int* const cpi; //error: error: uninitialized const ‘cpi’
cpi = &a; //error: assignment of read-only variable ‘cpi’
- cpi不能指向constant int
int* const cpi = &b; //error: invalid conversion from ‘const int*’ to ‘int*’
- cpi不能改变自身的值,即在初始化后,不能指向另一个变量
cpi = &c; //error: assignment of read-only variable ‘cpi’
- *cpi可以改变所指向的变量的值
*cpi = 8;
简单图
3 constant pointers to constants
初始代码:
int a = 2;
const int b = 4;
const int* const cpci = &b;
调试分析:
cpci必须在声明时被初始化,否则会报错
cpci自身的值不允许被修改,即在初始化后不能指向另一个变量
*cpci不允许修改所指向变量的值
cpci可以指向一个int或是const int
简单图
4 pointer to constant pointer to constant
初始代码:
const int b = 4;
const int* const cpci = &b;
const int* const* pcpci = &cpci;
调试分析:
cout<<**pcpci<<endl; // 4
简单图
& v.s. *(引用 v.s. 指针)
引用:就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。
1 传参
- 引用传参
#include <iostream>
void add(int& sum, int a, int b)
{
sum = a + b;
}
int main()
{
int a=3;
int b=4;
int c;
add(c, a, b);
std::cout<<c<<std::endl;
return 0;
}
output:
7
- 指针传参
#include <iostream>
void add(int* sum, int a, int b)
{
*sum = a + b;
}
int main()
{
int a=3;
int b=4;
int c;
add(&c, a, b);
std::cout<<c<<std::endl;
return 0;
}
- 两种传参方式区别
- 使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;
- 使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元
2 常引用
初始代码:
int a=3;
const int& rci = a;
调试分析:
- rci在初始化后就不能再被赋值了,但a仍可以被赋值
rci = 1; //error: assignment of read-only reference ‘rci’
a = 1; //that's okay.
传参常引用:
#include <iostream>
int add(int& a, int& b)
{
return a+b;
}
int main()
{
int a=3;
int b=4;
int c=add(a, b);
return 0;
}
- 上述代码是正确的,只是没什么意义,纯属为了测试。若在main函数加入
int d=add(3, 4); //error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’
则将报错。那是因为int&
的引用应该是变量,而不能是常数。
- 为了能处理常数的情况,可以改下add函数
int add(const int& a, const int& b)
{
return a+b;
}
这样,就可以了。除了能处理常数外,还有一个好处是,由于是常引用,故在该add函数内部不能改变a, b的原始值,更安全了。
3 引用作为返回值
#include <iostream>
const int& max(const int& a, const int& b)
{
return a>b ? a:b;
}
int main()
{
int a=3;
int b=4;
int c=max(a, b);
std::cout<<c<<std::endl;
return 0;
}
- output:
4
- 用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。
不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态
再看下另一个例子:
#include<iostream>
int ga;
int double_1(int a)
{
ga = 2*a;
return ga;
}
int& double_2(int a)
{
ga = 2*a;
return ga;
}
int main()
{
int a=2;
int& b=double_2(a);
b = 8;
std::cout<<ga<<std::endl;
return 0;
}
Output:
8
若在main中加上
int& b = double_1(a); //error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’
将报错。因为double_1()函数返回的只是一个常数值,在C++中,任何临时变量都是常数值const,而int&
引用的不能是常数值;但在double_2()函数中,函数返回的是ga,使得b引用它.
4 引用的其他特性
- 传递性
#include <iostream>
int main()
{
int a=3;
int& b=a;
int& c=b;
c = 5;
std::cout<<a<<std::endl;
return 0;
}
Output:
5
- int* &(指针引用) int* const&(指针常引用)
#include <iostream>
int main()
{
int a=3;
int* pi=&a;
int*& rpi = pi;
int* const& rcpi=&a;
*rcpi = 6;
std::cout<<a<<std::endl;
return 0;
}
Output:
6
int*& rpi=&a; //error:因为&a为常量
- read more
**觅思.澈**同学的[C++引用详解](http://www.cnblogs.com/gw811/archive/2012/10/20/2732687.html)