1.引用和指针的区别?
答:引用与指针的差别很大,指针是个变量,可以把它再变成指向别处的地址,然而, 建立引用时必须初始化,并且它不能再依附其他不同的变量了。可以这么说,引用是一个变/常量的别名。对其引用操作就等于对这个变/常量操作。C++中不为引用分配空间.
如下例:
#include <iostream>
using namespace std;
void main()
{
int a = 3, b = 4;
const int myconst = 10;
int &ref_a = a;
const int &ref_mycon = myconst;
cout << "ref_mycon = " << ref_mycon << ", myconst = " << myconst << endl;
cout << "ref_a = " << ref_a << ", a = " << a << endl;
ref_a = b;
cout << "ref_a = " << ref_a << ", a = " << a << endl;
ref_a = 5;
cout << "ref_a = " << ref_a << ", a = " << a << ", b = " << b << endl;
}
运行结果:
ref_mycon = 10, myconst = 10
ref_a = 3, a = 3
ref_a = 4, a = 4
ref_a = 5, a = 5, b = 4
2.const的用途
1)当const类型说明符用于说明变量时,其作用是冻结所定义的变量在定义域范围内为常量。C++要求用const说明的变量必须在定义时初始化赋值,以后不允许再有赋值
操作。const说明的常量和同类型的变量具有单向兼容性。即, const说明的常量可赋给变量,但反之则不允许。如下例中,变量y定义为整型常量,若要把变量赋给该常量将出错。
2)当const类型说明符用于说明引用时,则称为常引用。即不能通过引用名来修改原变量的值。int i = 100; constint &ri = i;
3) 当const类型说明符用于说明指针类型变量时,有三种情况:
冻结所定义的指针变量所指向的数据;
const int *p1 = &x; 定义指针所指向的量为常量
冻结指针的地址值;
Int* const p2 = &y; 定义指针自身为常量
或者冻结指针变量所指向的数据和指针的地址值。
const int *const p3 = &z;
4) 当const类型说明符用于函数的形式参数时,其作用是冻结实际参数在该函数内为常量,即该参数不允许在函数内被修改。形参可以是const int x或const int &rx。
5) 当const说明符用于函数的返回类型时,其作用是限定该函数返回的是个常量: const int func(); 该函数的调用定是 const int a = func();
6) 当const类型说明符用于类的成员函数时,其作用是不允许该成员函数修改对象的数据成员。 int classname::memfunc() const
3. C++语言增加引用类型主要用在三个方面
(1) 定义变量或对象的别名;
(2) 定义函数的参数为引用型;
(3) 定义函数的返回值类型是引用型。
注意:被引用的对象可以无名,但绝不可是临时对象。
#include <iostream>
using namespace std;
void main()
{
int i=110;
int * p = &i;
int & r = * p;
cout << i <<" "<< *p <<" "<< r << endl;
int *q = new int ( 220);
int & rq = *q;
cout << *q <<" "<< rq << endl;
delete q;
}
void fun(int x) {cout << "int x\n";}
1)将同一个名字用于同一作用域的不同类型的多个函数的情况叫重载。
2)什么样的函数是重载函数?
只有signature(函数名、参数和函数的const属性) 不同才
是重载,否则认为是相同的函数。(signature 不包括返
回值和参数的缺省值。)
函数前缀的访问控制不同也不是重载,而是相同的函数。
在不同的非名字空间作用域声明的函数不是重载。
#include <iostream>
using namespace std;
void fun(const int &x)
{
cout << "const int &x\n";
}
void fun(int &x)
{
cout << "int &x\n";
}
/*
void fun(int x) const
{
cout << "int x\n";
}
*/
void fun(int *x)
{
cout << "int *x\n";
}
class A
{
public:
A(){}
void foo() const
{cout << "foo() const \n";}
void foo()
{cout << "foo() \n";}
};
void main()
{
int a = 3;
int &ra = a;
int *pa = &a;
const int const_a = 3;
fun(a);
fun(ra);
fun(const_a);
fun(pa);
/* 函数的const属性区分重载 */
A obj1;
const A obj2;
obj1.foo();
obj2.foo();
}
5. 带默认值的函数
1)在C++语言中调用函数时,通常要为函数的每个形参给定
对应的实参。若没有给出实参,则按指定的默认值进行工
作。
2)当一个函数既有定义又有声明时,形参的默认值必须在声
明中指定,而不能放在定义中指定。
3)只有当函数没有声明时,才可以在函数定义中指定形参的
默认值。
4)默认值的定义必须遵守从右到左的顺序,如果某个形参
没有默认值,则它左边的参数就不能有默认值。如:
voidfunc1(int a, double b=4.5, int c=3); //合法
voidfunc1(int a=1, double b, int c=3); //不合法
注意:形参的默认值可以是全局常量、全局变量、表达式、函数调用,但不能为局部变量。因为默认值必须编译时静态确定。
//[例] 默认参数值的函数
#include <iostream>
using namespace std;
int d;
int f3(int n=3) {return n;} // 默认值为3
void f(int i=1,long l=2,int f = f3())
{ d=i+l+f; }
void main (void)
{
f (); printf ("f() sets d=%d\n",d);
f (2); printf ("f(2) sets d=%d\n",d);
f (2,3); printf ("f(2,3) sets d=%d\n",d);
f (2,3,4); printf ("f(2,3,4) sets d=%d\n",d);
}
运行结果:
f() sets d=6
f(2) sets d=7
f(2,3) sets d=8
f(2,3,4) sets d=9
Press any key to continue
6. new和delete 运算符
new
1)new运算符的语法格式为:new 类型名 (初始值)
其中,类型名指定了要分配存储空间的类型。
2)当动态申请单个变量或对象时,可以有初始值,也可以
没有初始值;当动态申请数组变量或对象时,不允许有初始值。
要注意的是,只有类的构造函数参数为空(void)或
全部参数都带有缺省值时,才可以动态申请数组对象。
3)当动态空间申请成功,new运算符按要求分配一块内存,
并返回指向该内存起始地址的指针;
当动态空间申请不成功时,new运算符返回空指针NULL。
delete
1)delete运算符用于释放由new运算符分配的动态存储空间。
delete运算符的语法格式为:
delete 指针
或 delete [ ]指针(释放数组)
其中,指针指向的必须是先前用new运算符分配的动
态存储空间。当释放动态分配的数组空间时,用第二
种格式。
(1)变量的分类
l 根据作用域: 可分为全局变量和局部变量。
l 根据生存周期:可分为静态存储方式和动态存储方式,具体地又分为自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)。
静态存储方式是指在程序运行期间分配固定的存储空间的方式,动态存储方式是在程序运行期间根据需要进行动态的分配存储空间的方式。
(2)变量的作用域和存储类别的关系
每一个变量均有作用域和存储类别两个属性,这些属性共同用于描述一个变量,这些不同类型的变量与存储位置的关系如下:
l 外部变量(全局变量)、静态外部变量、静态局部变量存储在静态存储区。
l 自动局部变量(局部变量默认为自动局部变量)、函数形参存储在动态存储区(即栈区)。
l 不论是静态存储区还是动态存储区均属于内存中的用户区。
l 而寄存器变量是存储在CPU寄存器中的而不是内存中。
(3)与作用域相关的几个属性:
l 局部变量:在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的,这种类型 的变量就称为“局部变量”。
l 全局变量:在函数外定义的变量,可以为本源文件中其它函数所公用,有效范围为从定义变量的位置开始到本源文件结束,这种类型的变量就称为“全局变量”。
(4)与存储类型相关的几个属性:
l atuo:在声明局部变量时,若不指定 static,默认均是 auto,这类变量都是动态分配存储空间的,数据存储在动态存储区中。
l static:在声明局部变量时,使用关键字 static 将局部变量指定为“静态局部变量”,这样在函数调用结束后不消失而保留原值,即占用的存储单元不释放,在下一次函数调 用时,该变量已有值就是上次函数调用结束时的值。
l register:在声明动态局部变量或者函数形参时,可将变量声明为register,这样编译系统就会为变量分配一个寄存器而不是内存空间,通过这种方式可提升对某些局部变 量频繁调用的程序的性能。(寄存器运算速度远高于内存)
l extern:用于扩展全局变量的作用域。
1) 比如如果函数想引用一个外部变量,但该外部变量在该函数后定义,那么这个函数需要使用 extern 来声明变量,这样才能使用在该函数后面定义的全局变量。
2) 此外,extern 还可以在多文件的程序中声明外部变量。
与const类似的,volatial看上去像常量——程序中不可以改变它。但是这不可靠:程序中不可以改变,系统却可能悄悄的改动
#include <iostream>
using namespace std;
void main(){
int a = 0;
cout << "逗号表达式的值:"<< (a=3*5, a*4) << endl;
}
运行结果: