• 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主要是防止隐式转换。

  • 相关阅读:
    559. N叉树的最大深度
    999. 车的可用捕获量
    1051. 高度检查器
    238. 除自身以外数组的乘积
    【Go】Go语言的%d,%p,%v等占位符的使用
    【Java】commons-lang3中DateUtils类方法介绍
    【Java】时间戳与Date相互转换
    【Linux】crontab定时任务用用法
    【Java】使用Lambda排序集合
    【PBFT】拜占庭容错
  • 原文地址:https://www.cnblogs.com/lzy820260594/p/11557329.html
Copyright © 2020-2023  润新知