C++总结体会

摘要:本文主要记录了在复习c++过程中的体会。

1、关于const

  1. 在c++中,const代表的是一种只读权限,即代表变量的值不可以再修改;
  2. 相比define而言,const修饰的数据可以有类型,更加地注重作用域;
  3. const修饰的变量用基础数据类型进行初始化时,只会标记到符号表,而不会分配内存;用变量名来进行初始化时,会分配内存;当const修饰的变量是一个自定义的数据类型时,那么也会分配内存;
  4. 只要进行了内存的分配,那么就可以通过指针的方式进行修改;
  5. 在c语言中const修饰的变量默认跨文件;而c++中的const修饰的变量默认作用于本文件,如果要实现跨文件,那么就应该借助extern;

2、关于typedef

  1. typedef可以用于给数据类型起别名:typedef  int  size,那么就可以用size来定义int型数据;
  2. typedef可以用于给某一个数组类型起别名:typedef  int   Arry[10],那么就可以用Arry来直接定义一个元素个数为10的int型的数组:Arry  buff={.......};
  3. typedef可以给一个指针类型起别名:typedef  int *  ptr,那么就可以直接用ptr来定义一个指针:ptr  p相当于int *  p;

3、关于引用reference

  1. 变量本质上就是某一个内存空间的代号,而引用本质上就是这个内存空间的代号2、代号3.......,所有的代号在本质上都一样,完全等价;
  2. 在定义一个变量时可以不对其进行初始化:int a;但是定义一个引用时则必须进行初始化:int  &b=a;这是因为既然起别名就要知道是为谁起别名,否则就没有意义,而被起别名的这段空间也必须是明确的才可以,正如我们给一个人起外号,必须要知道这个人是谁,我们不能说给某人起外号,给一个不知道的人起外号这都是没有意义的,所以引用不可以用于NULL;
  3. 对一个单一的变量建立引用是及其简单的,而给一个数组建立引用可以采用两种方式:第一种是借助typedef(typedef  int   Arry[10];Array &buff=arr;这里的arr是一个数组名);第二种是要将&buff括起来,表示数组名的引用(int (&buff)[10]=arr);
  4. 引用是通过指针常量来实现的(type  * const  ref=&val);这里的const是说明ref这个指针只可以指向val的空间,而不能指向其他的地址,这也就是为一个别名不能用于多个变量的实现原理;
  5. 对于指针的引用,在设置形参时,我们可以用二级指针的形式来表示  **p  ,也可以直接用引用来表示  *&p;
  6. 常量引用const  type &b=a;这里运用const的意思是不希望通过引用的方式将变量的值改变,多数应用在传参的过程中,不希望操作形参时将实参改变了;

关于指针的引用,这里加入一段代码,帮助理解:

 1 #include<iostream>
 2 
 3 using namespace std;
 4 
 5 struct Teacher
 6 {
 7     int age;
 8 };
 9 
10 void AgeChange(Teacher **teacher) { //这里的形参采用的是二级指针的方式
11     *teacher = new Teacher;    
12     (*teacher)->age = 10;
13 }
14 void Age_Change(Teacher *&teacher) {   //这里的形参就是一个引用
15     teacher->age = 100;
16 }
17 
18 int main() {
19     Teacher *MrLiu=NULL;    //定义一个指针变量
20     
21     AgeChange(&MrLiu);   //根据形参要求,这里传入的是指针的地址
22     cout << (*MrLiu).age << endl;
23 
24     Age_Change(MrLiu);
25     cout << (*MrLiu).age << endl;
26 
27     delete MrLiu;
28     
29     system("pause");
30     return 0;
31 }

4、关于extern"C"

在c++编译环境中,程序编译后,会发生函数的重载。而在c语言中并不会发生函数的重载,也就是说,当我们在c++环境中去调用c语言模块下的函数时,由于c++连接器会寻找重载后的函数,这当然是找不到的,那么此时就需要用到extern"C"。具体实现如下:

MyModule.h

 1 #ifndef MYMODULE_H
 2 #define MYMODULE_H
 3 
 4 #include<stdio.h>
 5 
 6 #if __cplusplus
 7 extern "C"{
 8 #endif
 9 
10     void func1();
11     int func2(int a,int b);
12 
13 #if __cplusplus
14 }
15 #endif
16 
17 #endif

MyModule.c

1 #include"MyModule.h"
2 
3 void func1(){
4     printf("hello world!");
5 }
6 int func2(int a, int b){
7     return a + b;
8 }

TestExternC.cpp

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<iostream>
 3 using namespace std;
 4 
 5 #if 0
 6 
 7     #ifdef __cplusplus
 8     extern "C" {
 9         #if 0
10             void func1();
11             int func2(int a, int b);
12         #else
13             #include"MyModule.h"
14         #endif
15     }
16 
17     #endif
18 
19 #else
20 
21     extern "C" void func1();
22     extern "C" int func2(int a, int b);
23 
24 #endif
25 
26 int main(){
27     func1();
28     cout << func2(10, 20) << endl;
29     return EXIT_SUCCESS;
30 }

5、关于class和struct

struct就是一个public权限下的class。

6、关于拷贝构造函数

有三种情况会调用拷贝构造函数:

  1. 用旧对象初始化新对象;
  2. 函数的形参是普通的对象,进行值传递会调用拷贝构造函数;
  3. 函数的返回值是一个普通的对象;

7、关于构造函数的调用

  1. 如果在一个类中,用户不写任何一个构造函数,那么系统默认会提供无参构造函数、析构函数、拷贝构造函数;
  2. 如果在一个类中,用户写了拷贝构造函数,那么系统就不再提供任何一种构造函数;
  3. 如果在一个类中,用户写了非拷贝构造的构造函数,那么系统不会再提供无参构造函数,但是依然会提供默认构造函数;

8、关于深拷贝和浅拷贝

我们知道,直接将一个对象赋值给另一个对象,这样的拷贝就是浅拷贝。如果被拷贝的对象里面只有基本的数据类型,那么这样的拷贝无非就是数据的相互赋值,完全没有问题。但是如果类中含有指针变量,指针变量在定义的时候是需要指向一段地址的,也就是说需要从堆中拿出一块内存,那么在这个指针进行拷贝的时候,会把这个指向的内存空间也进行拷贝;在堆中获取了空间以后,是需要释放的,那么在两个对象都被释放的时候,同一段内存就被释放了两次。这样就是违法的,会导致程序执行的崩溃,这也就是浅拷贝的弊端所在。

下面的例子就是浅拷贝:

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <iostream>
 3 
 4 using namespace std;
 5 
 6 class Person {
 7 public:
 8     Person() {
 9     }
10     Person(const char *name) {
11         m_name =(char*)malloc(strlen(name)+1);
12         strcpy(m_name,name);
13     }
14     ~Person() {
15         if (m_name!=NULL)
16         {
17             cout << "析构函数调用" << endl;
18             free(m_name);
19         }
20     }
21 private:
22     char *m_name;
23 };
24 void test() {
25     Person p1("abc");
26     Person p2(p1);    //系统自带的默认拷贝构造函数,直接崩溃,属于浅拷贝
27 }
28 
29 int main() {
30     test();
31 
32     system("pause");
33     return 0;
34 }

而所谓深拷贝,就是要避免浅拷贝存在的弊端,为新的对象创建新的空间,然后再进行拷贝,这样就不会导致同一段内存被释放两次。具体如下:

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <iostream>
 3 
 4 using namespace std;
 5 
 6 class Person {
 7 public:
 8     Person() {
 9     }
10     Person(const char *name) {
11         m_name =(char*)malloc(strlen(name)+1);
12         strcpy(m_name,name);
13     }
14     Person(const Person &person) {   //自定义的拷贝构造函数
15         m_name = (char*)malloc(strlen(person.m_name)+1);
16         strcpy(m_name,person.m_name);
17     }
18     ~Person() {
19         if (m_name!=NULL)
20         {
21             cout << "析构函数调用" << endl;
22             free(m_name);
23         }
24     }
25 private:
26     char *m_name;
27 };
28 void test() {
29     Person p1("abc");
30     Person p2(p1);    //拷贝构造函数
31 }
32 
33 int main() {
34     test();
35 
36     system("pause");
37     return 0;
38 }

9、关于explicit

explicit主要是防止隐式转换。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值