三目运算符
C语言返回变量的值 C++语言是返回变量本身。
代码:
int a = 10;
int b = 20;
(a < b ? a : b) = 30;
cout << a << endl;// 输出的结果是a=30;
(a < b ? a : b) 返回的是一个内存空间,内存地址。
如何做到?
原理如下:*(a>b?&a:&b)
const
struct Teacher
{
char name[64];
int age;
};
int oop(const Teacher *pT) // pt不能被修改。
{
// pT->age = 10;
return 1;
}
int op(Teacher *const pT) // pt的地址不能被修改。
{
pT->age = 10;
pt->null;//报错。
}
**- c语言中的const 能被修改
- C++中const是一个真正的常量**
代码如下:输出10;
const int a = 10;
int *p = NULL;
p = (int *)a;
*p = 20;
cout << a << endl;
原理如下:
*当我们执行 p = (int )a这行代码时,C++编译器会单独的为a开辟另一块空间,放改变后的变量,但是不会改变在符号表中的值。
const关键字结论:
结论: - C语言中的const变量
C语言中const变量是只读变量,有自己的存储空间
- C++中的const常量
可能分配存储空间,也可能不分配存储空间
当const常量为全局,并且需要在其它文件中使用
当使用&操作符取const常量的地址
const和#define的相同之处:
C++中const是一个真正意义上的常量,不能被修改,#define也可以定义一个常量。
const代码:(在C++中能编译通过)
const int a = 10;
const int b = 20;
int array[a + b];
const和#define的区别:
const常量是由编译器处理的,提供类型检查和作用域检查
宏定义由预处理器处理,单纯的文本替换
代码如下:
void fun1()
{
#define a 10
const int b = 20;
#undef a //卸载宏定义,当加入这行语句就是限制了a的作用域范围,这时候a就不能在b中使用。
}
void fun2()
{
cout << a << endl;
// cout << b << endl; // 在这个函数中不能被使用。
}
int main()
{
fun1();
fun2();
system(“pause”);
return 1;
}
C++中的引用
问题的提出,如果给a分配了一个内存空间,还能为这个内存空间再取一个别名吗?
代码感受:
int a = 10;
int &b = a; // 给a取了一个别名。
b = 100;//这行代码修改了,a的值。
cout << b << endl;// b=10;
1. 引用必须要初始化,下面代码错误。
int &b; //没有初始化。
2. 典型例子:数字交换
代码:
void swap(int a, int b)
{
int c = 0;
c = a;
a = b;
b = c;
}
int main()
{
int x = 10, y = 20;
swap(x, y);
}
上面的这个方式不能交换a和b,通过C语言中的指针改进,代码如下:
void swap2(int *a, int *b)
{
int c = 0;
c = *a;
*a = *b;
*b = c;
}// 用指针的方式交换两个数。
int main()
{
int x = 10, y = 20;
swap2(&x, &y);
}
通过引用改进:
void swap(int &a, int &b)
{
int c = 0;
c = a;
a = b;
b = c;
}
复杂数据类型记忆函数引用
代码如下:
void printfpt1(Teacher *pT)
{
cout << “printfpt1的age:” << pT->age << endl;
pT->age = 33;
}
void printfpt2(Teacher &pT)
{
cout << “printfpt2的age:” << pT.age << endl;
pT.age = 33;
}
void printfpt3(Teacher pT)
{
pT.age = 45; //这个pt
cout << “printfpt3的age:” << pT.age<< endl;
}
int main()
{
Teacher t1;
t1.age = 35;
//printfpt3(t1);//输出45
//printfpt2(t1); //输出33.
printfpt1(&t1);//输出33.
printfpt1(&t1);
}
引用的本质和意义。
引用的本质实质上是编译器帮我们取了一个地址。
当函数返回值为引用时
若返回栈变量,不能成为其它引用的初始值
不能作为左值使用
引用占不占内存空间
引用占内存空间,和其他所占的一样。代码:
struct Teacer {
int &a;
int &b;
};
printf("%d",sizeof(Teacer));
输出:16
引用的本质
1)引用在C++中的内部实现是一个常指针
Type& name Type* const name
2)C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。
3)从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做出的细节隐藏
引用的本质实际上是,C++编译器默认为我们取了一个地址。下图左边是普通写法,右边是实现原理。
引用的难点,函数的返回值当引用
当函数返回值为引用时
若返回栈变量
不能成为其它引用的初始值
不能作为左值使用
int getAA1()
{
int a;
a = 10;
return a; 函数运行完毕就释放了a的内存,return 时,a在寄存器中,此时,返回a的地址。
}
int& getAA2() // a的地址
{
int a; //当函数的返回值为引用时,若返回的是栈变量,不能作为其他引用的初始值,不能当左值。
a = 10;
return a; '//返回a本身,a地址,
}
int* getAA3()
{
int a;
a = 10;
return &a;
}
int main()
{
int a1 = getAA1();
int a2 = getAA2();
int &a3 = getAA2();// a3存放的是getAA2的地址,但是当getAA2 //当函数的返回值为引用时,若返回的是栈变量,不能作为其他引用的初始值,不能当左值。
cout << "a1 " << a1 << endl;
cout << "a2 " << a2<<endl; //返回10
cout << "a3 " <<a3<< endl; // a3打印出来以后是乱码,因为运行完getAA2之后,编译器分配给局部变量a的值被析构掉了,此时,再返回a的值时,就会出现一个随机的值。而这款内存的地址不变。
system(“pause”);
return 1;
}
若返回静态变量或全局变量
可以成为其他引用的初始值
即可作为右值使用,也可作为左值使用
代码:
int getAA1()
{
static int a;
a = 10;
return a;
}
int& getAA2() // a的地址
{
static int a; //当函数的返回值为引用时,若返回的是栈变量,不能作为其他引用的初始值,不能当左值。
a = 10;
return a;
}
int* getAA3()
{
static int a;
a = 10;
return &a;
}
int main()
{
int a1 = getAA1();
int a2 = getAA2();
int &a3 = getAA2();// a3存放的是getAA2的地址。 //当函数的返回值为引用时,若返回的是栈变量,不能作为其他引用的初始值,不能当左值。
cout << "a1 " << a1 << endl;
cout << "a2 " << a2<<endl;
cout << "a3 " <<a3<< endl; // a3出现乱码情况,原因如下。
system("pause");
return 1;
}
//程序运行完毕,就释放了内存。
若返回静态变量或全局变量 可以成为其他引用的初始值 即可作为右值使用,也可作为左值使用
函数引用返回变量本身
代码
int &a1()
{
static int a = 10;
a++;
cout << a << endl;
return a;
}
int main()// 第一次执行a1时,返回的是,静态变量a++;第二次执行时,把100赋给a,最后结果是101。
{
a1() = 100; //引用当左值。
a1();
int c = a1(); // c当右值。
system(“pause”);
return 1;
}
C语言指针(二级指针)的引用:
代码:
struct Teacher
{
char name[64];
int age;
};
int getTeacher(Teacher **p)// P指向pt1,
{
Teacher *tmp = NULL;// 为tmp在栈中开辟一块空间,
tmp = (Teacher *)malloc(sizeof(Teacher));//动态在堆中开辟一块内存空间。
if (p == NULL)
{
return -2;
}
tmp->age = 33;
*p = tmp;// 相当于pt1间接的指向tmp。
// 函数运行完毕后,释放tmp。
}
int main()
{
Teacher *pT1 = NULL;//首先在栈中开辟一个空间存放pt1
getTeacher(&pT1);//在被调函数中,p指向pt1,
cout << pT1->age << endl;
system(“pause”);
return 1;
}
常引用:
1 使用变量初始化const引用
int a = 10;
const int &b = a;
cout << b << endl;// 用变量初始化常引用
2 使用常量初始化const引用
const int &c = 41;
cout << c << endl;//用常量初始化常量引用。