网站首页 > 教程分享 正文
编译语言的翻译程序(编译器或解释器)总是按语法的规则来解释代码的,编程语言的设计者对语法规则的设计总有其合理性。C没有引用,C++试图做为C的升级版,引入引用有什么合理性?
1 引用的常量性质
引用具有常量性质,只允许有一次机会指向一个内存空间,避免了指针变量的东指西指引起的潜在问题。同时,引用不能指向NULL,也避免了指针指向NULL的一些问题。当然,也有一些场合是需要指向NULL的,这也是指针的价值所在,还有,指针也可以指向堆空间,当然,还可以应用在链式存储场合。引用是类型安全的,而指针不是 (引用比指针多了类型检查)。
2 引用的自解引用
指针的大规律使用用是用做函数参数,避免副本机制(当然,副本机制可以保证函数之间的独立性,避免副作用,有利有弊),当用作函数参数时,在函数体中需要解引用才可以起到改变参数指针指向的数据的作用的,如果不解引用,直接使用指针,改变的也就是指针本身(指针传址本质上也是传值,只是其值是一个地址),通常不是目的所在。解引用的写法繁琐难看,引用就可以由编译器实现自动解引用(所以指针的自增是地址的改变,而引用的自增是)。
3 返回引用做为左值
因为引用的自解引用,返回左值时用做左值时更便利。
class vector
{
int* data;
int size;
public:
……
int* operator[](int n)
{
assert(n>=0 && n<size);
return data+n;
}
};
用做左值时只能如此使用:
for(i=0;i<size;i++)
*v[i]=i;
*v[5]=555;
for(i=0;i<size;i++)
cout<<*v[i]<<endl;
看起来怪怪的,不够优雅,也不方便使用。
如果使用引用,就不存在上面的问题:
int& operator[](int n)
{
assert(n>=0 && n<size);
return data[n];
}
for(i=0;i<size;i++)
v[i]=i;
v[5]=5555;
for(i=0;i<size;i++)
cout<<v[i]<<endl;
4 拷贝构造函数需要使用引用做参数
首先不能使用值传递,因为产生对象副本,会造成重复构造。
如果使用对象指针,则如上述所说,使用起来繁琐难看。
5 重载流运算符,还真的只能使用引用
流运算符重载只能使用引用:
ostream& operator<<(ostream& of, vector& v)
{
of<<v.size<<": "<<'\n';
for(int i=0;i<v.size;i++)
of<<v[i]<<" "<<endl;
return of;
}
首先,流不能使用值传递。当我们将流作为参数传递给函数时,我们将使用引用,而不是值传递,主要原因是流是一种资源,如果我们将它作为值传递参数传递,程序将复制该资源,然后复制两次的资源也可能被释放两次,这可能会造成麻烦。此外,复制一个流还可以导致两个或多个流同时写入一个文件。
如果使用指针,编译时可以通过,但不能build:
ostream* operator<<(ostream* of, vector v) // 能编译通过,但不能连接
{
(*of)<<v.size<<": "<<'\n';
for(int i=0;i<v.size;i++)
(*of)<<v[i]<<" "<<endl;
return of;
}
附:
#include <iostream.h>
#include <assert.h>
#include <stdlib.h>
#define ANOTHER
// using namespace std;
class vector
{
int* data;
int size;
public:
vector()
{
data=NULL;
size=0;
}
vector(int* pData,int n){
data = pData;
size = n;
}
~vector()
{
delete[] data;
}
int setSize(int n)
{
delete[] data;
data = new int[n];
size = n;
return size;
}
int getSize() const
{
return size;
}
friend ostream& operator<<(ostream& of, vector& v);
friend ostream* operator<<(ostream* of, vector v);
#ifdef ANOTHER
int* operator[](int n)
{
assert(n>=0 && n<size);
return data+n;
}
#else
int& operator[](int n)
{
assert(n>=0 && n<size);
return data[n];
}
#endif
};
#ifdef ANOTHER
ostream* operator<<(ostream* of, vector v) // 能编译通过,但不能连接
{
(*of)<<v.size<<": "<<'\n';
for(int i=0;i<v.size;i++)
(*of)<<v[i]<<" "<<endl;
return of;
}
#else
ostream& operator<<(ostream& of, vector& v)
{
of<<v.size<<": "<<'\n';
for(int i=0;i<v.size;i++)
of<<v[i]<<" "<<endl;
return of;
}
#endif
int main()
{
int i;
vector v;
int size = 10;
v.setSize(size);
#ifdef ANOTHER
for(i=0;i<size;i++)
*v[i]=i;
*v[5]=555;
for(i=0;i<size;i++)
cout<<*v[i]<<endl;
#else
for(i=0;i<size;i++)
v[i]=i;
v[5]=5555;
for(i=0;i<size;i++)
cout<<v[i]<<endl;
#endif
int arr[4]={1,2,3,4};
vector vTest(arr,4);
cout<<vTest;
system("pause");
return 0;
}
-End-
猜你喜欢
- 2024-10-18 信号 - Linux Signal - 网络编程的相关信号
- 2024-10-18 干货 | 一文搞定 pytest 自动化测试框架(一)
- 2024-10-18 linux网络编程—tcp和udp基本函数调用过程及如何选择
- 2024-10-18 C语言之结构体基础(c语言结构体经典例题)
- 2024-10-18 linux定时器编程详解(包含代码)(linux定时器执行脚本)
- 2024-10-18 C语言学习第16篇---三目运算符和逗号表达式
- 2024-10-18 Linux网络编程相关高级I/O函数 - 用于创建文件描述符的函数
- 2024-10-18 干货 | 一文搞定 pytest 自动化测试框架(二)
- 2024-10-18 现代c++之移动构造,移动赋值,拷贝构造,拷贝赋值
- 2024-10-18 探索C语言断言:保证程序的健壮性和可靠性
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- css导航条 (66)
- sqlinsert (63)
- js提交表单 (60)
- param (62)
- parentelement (65)
- jquery分享 (62)
- check约束 (64)
- curl_init (68)
- sql if语句 (69)
- import (66)
- chmod文件夹 (71)
- clearinterval (71)
- pythonrange (62)
- 数组长度 (61)
- javafx (59)
- 全局消息钩子 (64)
- sort排序 (62)
- jdbc (69)
- php网页源码 (59)
- assert h (69)
- httpclientjar (60)
- postgresql conf (59)
- winform开发 (59)
- mysql数字类型 (71)
- drawimage (61)
本文暂时没有评论,来添加一个吧(●'◡'●)