C++中指针与引用的区别

[补充]什么是指针引用?即指针变量的引用:

//指针是变量,像int a;a就是一int型变量,引用int & ra=a;就让a和ra同等
//指针引用就是指针变量的引用!即让rpa和pa同等!
int *pa = &a;
int*& rpa = pa;
cout << "*pa="<<*pa << endl;
cout << "*rpa=" << *rpa << endl;
/*
*pa=5
*rpa=5
*/

pa = nullptr;
cout << "*rpa=" << *rpa << endl;
//运行时报错: 0xC0000005:  读取位置 0x00000000 时发生访问冲突。

 

C++引用详解

参考:[1]http://www.cnblogs.com/gw811/archive/2012/10/20/2732687.html

总结一下指针和引用的相同点和不同点:

★相同点:

●都是地址的概念;

指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

★不同点:

●指针是一个实体,而引用仅是个别名;

●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;

●引用没有const,指针有const,const的指针不可变;(具体指没有int& const a这种形式,而const int& a是有     的,  前者指引用本身即别名不可以改变,这是当然的,所以不需要这种形式,后者指引用所指的值不可以改变)

●引用不能为空,指针可以为空;不错在空引用这种语法!

●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;

●指针和引用的自增(++)运算意义不一样;(有什么区别?)

引用是类型安全的,而指针不是 (引用比指针多了类型检查)

为了进一步加深大家对指针和引用的区别,下面从编译的角度来阐述它们之间的区别:

程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。

引用和指针作为函数形参时的区别?

即在函数调用时对引用的传递和对指针的传递是不同的!

引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。

2.参考[2]SCOTT MEYERS. More Effective C++中文版: 35个改善编成与设计的有效方法[M]. 机械工业出版社, 2007.

More Effective C++基础议题:条款1:区别pointers和references。

1.指针可以为空指针(NULL、nullptr);但不存在空引用。即引用定义时必须初始化指向一明确的对象。

奇葩示例:一下情况C++未定义,结构不可预期:

char* pc=0;    //将指针pc设为null
char& rc=*pc;    //让引用rc代表指针pc的解引用(*)的值

2.引用必须初始化

string& rs;    //错误!引用必须初始化!
string s("xyzxyx");
string& rs=s;    //正确
string* ps;    //可以,但未初始化,不可用,野指针

不存在空引用,意味着,使用引用前可不需要检查引用。

而使用指针前需要检查指针是否为空。(在函数内部,对传进来的实参的有效性检查)

如:

void printDouble(const double& rd)
{//不需要检查rd的有效性,它一定代表有个double类型的对象
    cout<<rd;    
}

void printDouble(const double* pd)
{
    if(pd)检查是否为空指针
    {
        cout<<*pd;
    }
}

指针与引用的一个重大差别是 :指针可以被重新赋值,指向另外一个对象;而引用总是指向(代表)它最初获得的那个对象。

string s1("Nancy");
string s2("Clancy");

string& rs=s1;    //rs代表了s1,rs就是s1的别名
string* ps=&s1;    //ps指向s1,但ps还可以指向其他string对象

rs=s2;    //是个赋值语句,相当于s1=s2;    rs仍然代表s1,s1="Clancy"

p2=&s2;    //指针从定向赋值语句,现在指针ps指向了s2,s1没有变化

另外:以下情况需要使用引用:

1.重载[]操作符时:(这个操作符很特别地必须返回某种“能够被当做assignment赋值对象"的东西:

vector<int> v(10);

v[5]=10;    //assignment的赋值对象是operatpr[]的返回值

如果vector的重载[]操作符的成员函数返回的是指针,

则上面的那行代码应该写出以下形式:

*v[5]=10;

 为了易于理解,应该总是令operator[]返回一个引用。

另外处理对象的连续赋值:

int x,y,z;
x=y=z=5;
//上一句等价于:
x=(y=(z=15));

I/O输出流的连续操作:

std::cout<<x<<y<<z;
int a, b;
a = b = 10;
cout <<  a << b << endl;


_Myt& __CLR_OR_THIS_CALL operator<<(int _Val)
		{	// insert an int
		ios_base::iostate _State = ios_base::goodbit;
		const sentry _Ok(*this);

		if (_Ok)
			{	// state okay, use facet to insert
			const _Nput& _Nput_fac = _USE(this->getloc(), _Nput);
			ios_base::fmtflags _Bfl =
				this->flags() & ios_base::basefield;
			long _Tmp = (_Bfl == ios_base::oct
				|| _Bfl == ios_base::hex)
				? (long)(unsigned int)_Val : (long)_Val;

			_TRY_IO_BEGIN
			if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
				_Myios::fill(), _Tmp).failed())
				_State |= ios_base::badbit;
			_CATCH_IO_END
			}

		_Myios::setstate(_State);
		return (*this);
		}

参考[3]Effective C++(第三版)item10、11:

item10:令对象的operator= 返回一个reference to *this

item11:在operator= 中处理”自我赋值“

class Widget{
public:
    Widget& operator=(const Widget& rhs)
    {
        ...
        return *this;
    }
    Widget& operator+=(const Widget& rhs)
    {
        ...
        return *this;
    }
    ...
};

2.处理自我赋值的情况:a=a:

class Bitmap{};
class Widget{
    ...
private:
    Bitmap* pb;    //指向一个从heap分配而得到的对象
};

Widget& Widget::operator=(const Widget& rhs)
{
    if(this==&rhs)    //证同测试 identify test
        return *this;   
    delete pb;
    pb=new Bitmap(*rhs.pb);
    retrun *this;
}

参考[2]Meyers, Scott. Effective C++, third edition[M]. Publishing House of Electronics Industry :Pearson, 2006.

条款11:在operator=中处理”自我赋值“

和条款29:为异常安全而努力是值得的。

异常安全函数的三个保证。

用对象管理资源、智能指针的使用。

在operator=函数内精心安排代码的语句排列顺序(确保代码不但”异常安全“而且”自我赋值“安全)的一个替代方案是使用所谓的

copy and swap技术:

class Widget{
...
    void swap(Widget& rhs);    //交换*this数据和rhs数据
    Widget& operator=(const Widget& rhs);
...
};

Widget& Widget::operator=(const Widget& rhs)
{
    Widget temp(rhs);    //为rhs数据制作一个临时副本
    swap(temp);            //将*this的数据和上述副本的数据进行交换
    return *this;
}

参考[1]http://blog.sina.com.cn/s/blog_673ef8130100imsp.html 

C++ 指针与引用的区别

猜你喜欢

转载自blog.csdn.net/m0_37357063/article/details/81910935
今日推荐