`

《认清C++语言》---引用和指针

 
阅读更多

1、 首先要认识到不存在类似于空引用(null reference)这样的东西。引用必须要指代某个对象,因此,如果有一个用于指代另外一个对象的变量,但是有可能没有这么一个可供指代的对象,这时就应该把这个变量声明成指针,因为这样就可以将它设为空值(null)了。反之,如果这个变量必须指代一个对象,即我们将这个变量设计成不允许为空值,那么这时基本上应该将这个变量声明成引用。

2、 因为引用总是要指代一个对象,C++要求引用必须初始化。

std::string& ace; //Err! 引用必须初始化

std::string sace(rid);

std::string& ace= sace; //Ok! 引用ace指向sace

指针并没有类似的限制:

std::string *ps; //未初始化的指针,合法但具有风险!

3、 不存在空引用这个事实说明,使用引用比使用指针更高效,因为在使用引用前不需要测试它是否有效:

void ACEPrint(const double& db)

{

std::cout<<db; //没有必要测试db,因为引用必然指向某个对象

}

而与之相反,指针通常需要检查其是否为空:

void ACEPrint(const double *db)

{

if(db) //检查是否是空指针

{

std::cout<<db;

}

}

4、 指针和引用另一个重要不同点在于:指针可以被重新赋值用以指向另外一个不同的对象;而引用则始终指向初始化时它所指代的对象:

std::string ace1(hw);

std::string ace2(rid);

std::string& race = ace1; //race指代ace1

std::string *pace = ace1; //pace指向ace1

race = ace2; //race依然指代ace1,但ace1的值现在是“rid

pace = &ace2; //pace现在指向ace2ace1的值不变

5、 总之,当需要考虑以下两种情况时,应该使用指针:有可能什么也不指向(这种情况下,我们可以把指针设为空值);需要能够在不同时候指向不同的对象(这种情况下可以更改指针的指向)。

当我们知道总是会指向某一个对象并且一旦指定那个对象,就不会再指向其他对象时,应该使用引用。

6、 还有一种情况应该使用引用,即当实现某些操作符的时候。最常见的例子是[]操作符。这个操作符通常需要返回一个值作为(下一个)赋值语句的赋值目标:

vector<int> v(10);

v[5] = 10;

我们可以看到,如果[]操作符返回一个指针,那么上面最后一条语句就必须写成:

*v[5] = 10;

这让v看起来像是一个关于指针的向量,而实际并非如此。因此,绝大多数情况下[]操作符都应该返回一个引用。

P.S引用是一个现有对象的别名,用对象来初始化引用后,那么对象的名字或引用的名字都可以用于指向该对象。人们常常将引用和指针混淆,原因大概在于C++编译器通常采用指针的方式实现引用,但引用实际不是指针,其行为和指针并不相同。如前面所说,引用和指针存在三大区别:一是不存在空引用;二是所有引用都要初始化;三是一个引用永远指向用来对它初始化的那个对象。

一个指向非常量的引用是不可以用字面值或临时值进行初始化的:

double &aced = 13.4; //Err

template<typename T>

void swap(T &a, T&b)

{

T temp(a);

a = b;

b = temp;

}

swap(std::string(Hello), std::string(, World)); //Err

然而,一个指向常量的引用就可以:

const double &aced = 13.4; //OK

template<typename T>

T add(const T &a, const T &b)

{

return a+b;

}

...

const std::string &greeting = add(std:string(Hello), std::string(, World)); //OK!

当一个指向常量的引用采用一个字面值来初始化时,该引用实际上被设置成指向“采用该字面值初始化”的一个临时位置。)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics