醴陵 网站建设/seo优化信
引用:
//引用就是别名,下面mum是num的别名,这两个变量是一个变量,只不过名字不同而已
#include<iostream>
using namespace std;
int main()
{
int num;
int &mum=num; //定义num的别名mum
num=999;
cout<<"mum:"<<mum<<endl;
cout<<"num:"<<num<<endl;
return 0;
}
别名mnm前面的符合&不是取址运算符,而是引用运算符,虽然它们符合
相同,但是功能却不一样
-----------------------------------------------------
查看别名的地址:
//下面的例子显示变量a及其别名ra的地址相同
#include<iostream>
using namespace std;
int main()
{
int a;
int &ra=a; //定义a的别名ra(注意定义引用时一定要同时对该引用进行初始化)
a=999;
cout<<"&a:"<<&a<<endl;
cout<<"&ra:"<<&ra<<endl;//输出相同的地址
return 0;
}
---------------------------------------------------------
引用就是别名常量,跟了一个变量,就永远跟这个变量
//下面的例子显示我们将ra定义为a的别名。这样ra这个
//别名就只属于变量a,它不会变成b的别名。变量b只能将
//自己的值赋给这个ra,它不能改变ra的地址,比如说它不能
//让ra变成自己的别名
#include<iostream>
using namespace std;
int main()
{
int a;
int &ra=a; //定义a的别名ra
a=999;
cout<<"&a:"<<&a<<endl;
cout<<"&ra:"<<&ra<<endl;
int b=888;
ra=b;
cout<<"&a:"<<&a<<endl;
cout<<"&ra:"<<&ra<<endl;
cout<<"&b:"<<&b<<endl;
cout<<"a:"<<a<<endl;
cout<<"ra:"<<ra<<endl;
cout<<"b:"<<b<<endl;
ra=1;
cout<<"a:"<<a<<endl;
cout<<"ra:"<<ra<<endl;
cout<<"b:"<<b<<endl;
return 0;
}
//因此这个ra又可看作是个别名常量,它是a的别名这个身份我们
//无法改变,我们能改变的只是它所引用的值。
--------------------------------------------------------
对象的引用:
//注意类不能定义个别名,因为类没有具体的内存地址
//下面例子是给一个类的对象定义个别名
#include<iostream>
using namespace std;
class Human
{
public:
int get(){return i;}
void set(int x){i=x;}
private:
int i;
};
int main()
{
Human Mike;
Human &rMike=Mike;
rMike.set(123);
cout<<rMike.get()<<endl;
return 0;
}
-------------------------------------------------------------
空引用:
我们知道指针进行删除操作后,需要将它们赋为空,引用却不需要这么做,这是因为
引用是原来对象的别名,假如该对象存放在栈中,那么在对象超出作用域时别名会和对象
一起消失。假如该对象存放在堆中,由于堆中内存空间必须使用指针来访问,因此用不着
别名.
--------------------------------------------------------------
按值传递:
//通过值来传递函数参数
//下面程序运行后,swap函数交换的是main()函数中a,b的副本的值.而不是a,b的本身
//所以主程序中的a,b并没有交换,这种的传递方式是按值传递
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int c;
cout<<"swap函数中,交换前,a:"<<a<<"b:"<<b<<endl;
c=a;
a=b;
b=c;
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
}
int main()
{
int a=3,b=4;
cout<<"主程序中,交换前,a:"<<a<<"b:"<<b<<endl;
swap(a,b);
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
//输出结果可以看出主程序中的a,b并没有交换
}
//假如将a和b按值传递给swap函数,那么编译器会自动在栈中
//创建a和b的拷贝,然后将a和b的拷贝传递给swap函数。在swap
//函数中对a,b的拷贝进行交换。因此我们看到的输出语句,a,b
//确实进行了交换,只不过交换的是a,b的副本。
-----------------------------------------------------------
按址传递:
//就是按地址的方式传递函数参数,程序运行后主程序中a,b的值交换了
#include<iostream>
using namespace std;
void swap(int *a,int *b) //这里的两个参数是两个指针用来保存传递来的地址
{
int c;
cout<<"swap函数中,交换前,a:"<<*a<<"b:"<<*b<<endl;
c=*a;
*a=*b;
*b=c;
cout<<"swap函数中,交换后,a:"<<*a<<"b:"<<*b<<endl;
}
int main()
{
int a=3,b=4;
cout<<"主程序中,交换前,a:"<<a<<"b:"<<b<<endl;
swap(&a,&b); //取a,b的地址
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
//输出结果可以看出主程序中的a,b交换了
}
--------------------------------------------------------
按别名传递:
//就是按别名的方式传递函数参数,实现效果和用传址相同
把指针作为函数的接收参数虽然能够正常使用,但是它却不易阅读,使用不方便
#include<iostream>
using namespace std;
void swap(int &a,int &b)
{
int c;
cout<<"swap函数中,交换前,a:"<<a<<"b:"<<b<<endl;
c=a;
a=b;
b=c;
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
}
int main()
{
int a=3,b=4;
cout<<"主程序中,交换前,a:"<<a<<"b:"<<b<<endl;
swap(a,b); //注意这里的参数a,b
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
return 0;
}
-------------------------------------------------------------
利用指针返回多值:
//当然也可以用引用 ,只有把指针换成引用即可
#include<iostream>
using namespace std;
int func(int a,int*b,int*c);
int main()
{
int a=1,b=2,c=3;
cout<<"主程序,调用func函数前...\n";
cout<<"a:"<<a<<endl<<"b:"<<b<<endl<<"c:"<<c<<endl;
func(a,&b,&c);
cout<<"主程序,调用func函数后...\n";
cout<<"a:"<<a<<endl<<"b:"<<b<<endl<<"c:"<<c<<endl;
return 0;
}
int func(int a,int*b,int*c)//这里利用参数是值或地址的不同组合,实现改变a,b,c的值不同
{
cout<<"func函数中,计算前...\n";
cout<<"a:"<<a<<endl<<"b:"<<*b<<endl<<"c:"<<*c<<endl;
a=a+1;
*b=(*b)*(*b);
*c=(*c)*(*c)*(*c);
cout<<"func函数中,计算后...\n";
cout<<"a:"<<a<<endl<<"b:"<<*b<<endl<<"c:"<<*c<<endl;
return a;
}
----------------------------------------------------------------
//我们也可以把a作为返回的判断值,把*b和*c作为运算的返回值,用该种方法
//可以实现汇报执行程序时的非法操作信息。
#include<iostream>
using namespace std;
int func(int a,int*b,int*c);
int main()
{
int a,b,c;
int check;
cout<<"请输入要进行运算的数字,";
cout<<"你输入的数字将作为圆的半径和正方形的边长:";
cin>>a;
check=func(a,&b,&c);
if(check)
{
cout<<"输入的数字超过计算范围!\n";
}
else
{
cout<<"圆的面积为:"<<b<<endl;
cout<<"正方形的面积:"<<c<<endl;
}
return 0;
}
int func(int a,int*b,int*c)
{
if(a>20000)
{
a=1;
}
else
{
*b=a*a*3.14;
*c=a*a;
a=0;
}
return a;
}
---------------------------------------------------------
按值传递对象时,会像传递变量那样建立一个该对象的拷贝,而从函数返回一个对象时,
也要建立这个被返回的对象的一个拷贝。如果对象的数据非常多时,这种拷贝带来的内存
开销是相当大的。(怎么解决该问题:可以使用传址或传引用的方式)
//通过下面按值传递的程序可以看出将一个对象按值传递给一个函数,会调用
//两次复制构造函数和两次析构函数,这样系统的开销是很大的。
//两次调用复制构造函数分别是传递参数时(传地址)和返回值时(返回地址)
#include<iostream>
using namespace std;
class A
{
public:
A(){cout<<"执行构造函数创建一个对象\n";}
A(A&){cout<<"执行复制构造函数创建该对象的副本\n";}
~A(){cout<<"执行析构函数删除该对象\n";}
};
A func(A one)
{
return one;//返回方式也是按值返回,所以又会调用复制构造函数
//再次创建一个返回值one的副本
}
int main()
{
A a; //在这一行定义了一个类A的对象a
//创建一个对象会自动调用构造函数
func(a); //将对象a按值传递到func函数中
//这时会自动调用复制构造函数创建对象a的一个副本,然后将这个副本传递到func函数中去
//由于func函数的返回值没有赋给任何对象,因此这个返回的临时对象也就被丢弃了
//这时自动调用析构函数来释放这个临时对象所占用的内存
return 0;
}
-------------------------------------------------------------
//按址传递对象:
//如下例子按址传递,只调用一次复制构造函数
//
#include<iostream>
using namespace std;
class A
{
public:
A(){cout<<"执行构造函数创建一个对象\n";}
A(A&){cout<<"执行复制构造函数创建该对象的副本\n";}
~A(){cout<<"执行析构函数删除该对象\n";}
};
A* func(A *one)
{
return one;//返回地址则不会调用复制构造函数,如果改为return *one;则又要调用 //一次复制构造函数
}
int main()
{
A a;
func(&a); //传递地址所以不会调用复制构造函数
return 0;
}
----------------------------------------------------------------------
//引用就是别名,下面mum是num的别名,这两个变量是一个变量,只不过名字不同而已
#include<iostream>
using namespace std;
int main()
{
int num;
int &mum=num; //定义num的别名mum
num=999;
cout<<"mum:"<<mum<<endl;
cout<<"num:"<<num<<endl;
return 0;
}
别名mnm前面的符合&不是取址运算符,而是引用运算符,虽然它们符合
相同,但是功能却不一样
-----------------------------------------------------
查看别名的地址:
//下面的例子显示变量a及其别名ra的地址相同
#include<iostream>
using namespace std;
int main()
{
int a;
int &ra=a; //定义a的别名ra(注意定义引用时一定要同时对该引用进行初始化)
a=999;
cout<<"&a:"<<&a<<endl;
cout<<"&ra:"<<&ra<<endl;//输出相同的地址
return 0;
}
---------------------------------------------------------
引用就是别名常量,跟了一个变量,就永远跟这个变量
//下面的例子显示我们将ra定义为a的别名。这样ra这个
//别名就只属于变量a,它不会变成b的别名。变量b只能将
//自己的值赋给这个ra,它不能改变ra的地址,比如说它不能
//让ra变成自己的别名
#include<iostream>
using namespace std;
int main()
{
int a;
int &ra=a; //定义a的别名ra
a=999;
cout<<"&a:"<<&a<<endl;
cout<<"&ra:"<<&ra<<endl;
int b=888;
ra=b;
cout<<"&a:"<<&a<<endl;
cout<<"&ra:"<<&ra<<endl;
cout<<"&b:"<<&b<<endl;
cout<<"a:"<<a<<endl;
cout<<"ra:"<<ra<<endl;
cout<<"b:"<<b<<endl;
ra=1;
cout<<"a:"<<a<<endl;
cout<<"ra:"<<ra<<endl;
cout<<"b:"<<b<<endl;
return 0;
}
//因此这个ra又可看作是个别名常量,它是a的别名这个身份我们
//无法改变,我们能改变的只是它所引用的值。
--------------------------------------------------------
对象的引用:
//注意类不能定义个别名,因为类没有具体的内存地址
//下面例子是给一个类的对象定义个别名
#include<iostream>
using namespace std;
class Human
{
public:
int get(){return i;}
void set(int x){i=x;}
private:
int i;
};
int main()
{
Human Mike;
Human &rMike=Mike;
rMike.set(123);
cout<<rMike.get()<<endl;
return 0;
}
-------------------------------------------------------------
空引用:
我们知道指针进行删除操作后,需要将它们赋为空,引用却不需要这么做,这是因为
引用是原来对象的别名,假如该对象存放在栈中,那么在对象超出作用域时别名会和对象
一起消失。假如该对象存放在堆中,由于堆中内存空间必须使用指针来访问,因此用不着
别名.
--------------------------------------------------------------
按值传递:
//通过值来传递函数参数
//下面程序运行后,swap函数交换的是main()函数中a,b的副本的值.而不是a,b的本身
//所以主程序中的a,b并没有交换,这种的传递方式是按值传递
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int c;
cout<<"swap函数中,交换前,a:"<<a<<"b:"<<b<<endl;
c=a;
a=b;
b=c;
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
}
int main()
{
int a=3,b=4;
cout<<"主程序中,交换前,a:"<<a<<"b:"<<b<<endl;
swap(a,b);
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
//输出结果可以看出主程序中的a,b并没有交换
}
//假如将a和b按值传递给swap函数,那么编译器会自动在栈中
//创建a和b的拷贝,然后将a和b的拷贝传递给swap函数。在swap
//函数中对a,b的拷贝进行交换。因此我们看到的输出语句,a,b
//确实进行了交换,只不过交换的是a,b的副本。
-----------------------------------------------------------
按址传递:
//就是按地址的方式传递函数参数,程序运行后主程序中a,b的值交换了
#include<iostream>
using namespace std;
void swap(int *a,int *b) //这里的两个参数是两个指针用来保存传递来的地址
{
int c;
cout<<"swap函数中,交换前,a:"<<*a<<"b:"<<*b<<endl;
c=*a;
*a=*b;
*b=c;
cout<<"swap函数中,交换后,a:"<<*a<<"b:"<<*b<<endl;
}
int main()
{
int a=3,b=4;
cout<<"主程序中,交换前,a:"<<a<<"b:"<<b<<endl;
swap(&a,&b); //取a,b的地址
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
//输出结果可以看出主程序中的a,b交换了
}
--------------------------------------------------------
按别名传递:
//就是按别名的方式传递函数参数,实现效果和用传址相同
把指针作为函数的接收参数虽然能够正常使用,但是它却不易阅读,使用不方便
#include<iostream>
using namespace std;
void swap(int &a,int &b)
{
int c;
cout<<"swap函数中,交换前,a:"<<a<<"b:"<<b<<endl;
c=a;
a=b;
b=c;
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
}
int main()
{
int a=3,b=4;
cout<<"主程序中,交换前,a:"<<a<<"b:"<<b<<endl;
swap(a,b); //注意这里的参数a,b
cout<<"swap函数中,交换后,a:"<<a<<"b:"<<b<<endl;
return 0;
}
-------------------------------------------------------------
利用指针返回多值:
//当然也可以用引用 ,只有把指针换成引用即可
#include<iostream>
using namespace std;
int func(int a,int*b,int*c);
int main()
{
int a=1,b=2,c=3;
cout<<"主程序,调用func函数前...\n";
cout<<"a:"<<a<<endl<<"b:"<<b<<endl<<"c:"<<c<<endl;
func(a,&b,&c);
cout<<"主程序,调用func函数后...\n";
cout<<"a:"<<a<<endl<<"b:"<<b<<endl<<"c:"<<c<<endl;
return 0;
}
int func(int a,int*b,int*c)//这里利用参数是值或地址的不同组合,实现改变a,b,c的值不同
{
cout<<"func函数中,计算前...\n";
cout<<"a:"<<a<<endl<<"b:"<<*b<<endl<<"c:"<<*c<<endl;
a=a+1;
*b=(*b)*(*b);
*c=(*c)*(*c)*(*c);
cout<<"func函数中,计算后...\n";
cout<<"a:"<<a<<endl<<"b:"<<*b<<endl<<"c:"<<*c<<endl;
return a;
}
----------------------------------------------------------------
//我们也可以把a作为返回的判断值,把*b和*c作为运算的返回值,用该种方法
//可以实现汇报执行程序时的非法操作信息。
#include<iostream>
using namespace std;
int func(int a,int*b,int*c);
int main()
{
int a,b,c;
int check;
cout<<"请输入要进行运算的数字,";
cout<<"你输入的数字将作为圆的半径和正方形的边长:";
cin>>a;
check=func(a,&b,&c);
if(check)
{
cout<<"输入的数字超过计算范围!\n";
}
else
{
cout<<"圆的面积为:"<<b<<endl;
cout<<"正方形的面积:"<<c<<endl;
}
return 0;
}
int func(int a,int*b,int*c)
{
if(a>20000)
{
a=1;
}
else
{
*b=a*a*3.14;
*c=a*a;
a=0;
}
return a;
}
---------------------------------------------------------
按值传递对象时,会像传递变量那样建立一个该对象的拷贝,而从函数返回一个对象时,
也要建立这个被返回的对象的一个拷贝。如果对象的数据非常多时,这种拷贝带来的内存
开销是相当大的。(怎么解决该问题:可以使用传址或传引用的方式)
//通过下面按值传递的程序可以看出将一个对象按值传递给一个函数,会调用
//两次复制构造函数和两次析构函数,这样系统的开销是很大的。
//两次调用复制构造函数分别是传递参数时(传地址)和返回值时(返回地址)
#include<iostream>
using namespace std;
class A
{
public:
A(){cout<<"执行构造函数创建一个对象\n";}
A(A&){cout<<"执行复制构造函数创建该对象的副本\n";}
~A(){cout<<"执行析构函数删除该对象\n";}
};
A func(A one)
{
return one;//返回方式也是按值返回,所以又会调用复制构造函数
//再次创建一个返回值one的副本
}
int main()
{
A a; //在这一行定义了一个类A的对象a
//创建一个对象会自动调用构造函数
func(a); //将对象a按值传递到func函数中
//这时会自动调用复制构造函数创建对象a的一个副本,然后将这个副本传递到func函数中去
//由于func函数的返回值没有赋给任何对象,因此这个返回的临时对象也就被丢弃了
//这时自动调用析构函数来释放这个临时对象所占用的内存
return 0;
}
-------------------------------------------------------------
//按址传递对象:
//如下例子按址传递,只调用一次复制构造函数
//
#include<iostream>
using namespace std;
class A
{
public:
A(){cout<<"执行构造函数创建一个对象\n";}
A(A&){cout<<"执行复制构造函数创建该对象的副本\n";}
~A(){cout<<"执行析构函数删除该对象\n";}
};
A* func(A *one)
{
return one;//返回地址则不会调用复制构造函数,如果改为return *one;则又要调用 //一次复制构造函数
}
int main()
{
A a;
func(&a); //传递地址所以不会调用复制构造函数
return 0;
}
----------------------------------------------------------------------