
C++
文章平均质量分 52
C++学习
王大队长
这个作者很懒,什么都没留下…
展开
-
模板函数中参数为数组
【代码】模板函数中参数为数组。原创 2023-04-20 13:17:37 · 258 阅读 · 1 评论 -
模板辅助函数中的swap
比如我们想交换两个 vector,显然上面的代码就无能为力了。容器内自带的 swap 函数,这样就能调用标准的 swap 方法中有两个元素而不是容器自带的swap 方法,显然两个参数的 swap 方法更符合我们的直觉,并且只要你自定义的类实现了像vector一样的 swap 方法就也可以使用 std::swap 来交换你自定义的类!注意到我们的注释:在常数时间内交换两个 vector 的元素,全局的 std::swap 函数被特例化因此 std::swap(v1, v2) 被喂到这个函数。原创 2023-04-19 17:39:11 · 262 阅读 · 0 评论 -
为多态基类声明virtual析构函数
如上面代码所示,我们的三个工厂函数都是用的基类来指向的,因为我们用的 new 来创建对象,所以自然要用 delete 释放掉,可是问题来了,我们的ptk指针是用基类指向子类对象,那么我们释放的时候是调用基类的析构还是子类的析构函数呢?因为这里是静态联编,在运行之前,编译器只知道ptk是 TimeKeeper类型的,自然是调用基类的析构,但是我们实例化的是一个子类啊,你调用基类的析构,那子类中万一有一些基类没有的元素呢?问题的关键在于在实现多态的时候,堆区的内存可能会泄露,这是要用虚析构!原创 2023-02-25 22:01:51 · 440 阅读 · 0 评论 -
若不想使用编译器自动生成的函数,就应该明确拒绝
但是如果我们为了严谨和安全性不想这样呢,我们可能想拷贝的时候不要全部的东西全拷贝了,毕竟世界上没有两片相同的树叶,那你当然可以自己定义拷贝构造函数,但是如果你更狠直接拒绝拷贝这种行为,你该怎么办呢?我们知道,在cpp中,哪怕我们没有定义拷贝构造函数编译器也会自动帮我们生成一个拷贝构造函数,例如在下面的代码中,我们定义的person类并没有定义拷贝构造函数,但是我们依然能用'p2=p1'。在上面的代码中,我们仅仅声明了拷贝构造函数而没有实现并且定义为private的,此时编译器便组织了我们的拷贝操作。原创 2023-02-25 20:26:00 · 123 阅读 · 0 评论 -
基于范围的for循环
【代码】基于范围的for循环。转载 2022-10-01 10:27:07 · 94 阅读 · 0 评论 -
继承和动态内存分配
我们来看看拷贝构造函数,父类的拷贝构造函数没什么好说的,主要是子类,子类先用初始化列表将要传进来进行拷贝的子类对象传给父类,这是因为首先父类引用可以指向子类所以可以传,又因为我们对子类进行拷贝,子类中还有一些继承父类的组件得传给父类才能使得全部拷贝进去吧,否则只拷贝了子类自己特有的部分,因为我们必须传!最后我们看看重载赋值运算符,其实很容易想到重载赋值运算符其实和拷贝构造函数的功能是差不多的,因此基类的重载赋值运算符和拷贝构造函数的实现差不多。这里和上面子类的拷贝构造函数一样,也要先将父类拷贝了。原创 2022-09-19 09:47:27 · 403 阅读 · 0 评论 -
类继承与多态
如上代码,我们定义了一个基类Base_Person,其定义了私有的属性以及公有的构造函数以及show函数。我们也定义了一个子类Teacher,其继承了Base_Person类,在基类的基础上新增了自己的私有属性duty和自己的构造函数。并且注意到我们的还定义了一个Teacher的拷贝构造函数。最后我们在派生类中调用了基类的方法。因为派生类不能直接访问基类的私有成员,而必须通过基类方法进行访问。,所以我们的构造函数以列表初始化的方式先初始化了Base_Person基类(否则将使用默认的基类构造函数),原创 2022-09-17 11:31:25 · 349 阅读 · 0 评论 -
定位new运算符
本文主要讲解定位new运算符的析构函数的显式调用问题。在上面那篇文章中已经提到用将定位new运算符来创建新的类对象后,当该对象消亡是时,程序并不会自动地调用其析构函数,所以必须显示地调用析构函数并且对于使用定位new运算符创建的对象,应以与创建顺序相反的顺序进行删除。原因在于,晚创建的对象可能依赖于早创建的对象。另外,仅当所有对象都被销毁后,才能释放用于储存这些对象的缓冲区。原创 2022-09-12 11:05:32 · 547 阅读 · 0 评论 -
重载与友元
于是我们可以重载原创 2022-09-09 10:34:57 · 698 阅读 · 0 评论 -
使用VScode将c++代码反汇编
我们在学习C++语言的时候有时需要把C++代码反汇编成汇编代码,通过汇编代码查看代码是怎么运行的,函数形参、局部变量是怎么压栈,函数是怎么调用的,栈指针是怎么跳转工作等等,这样能更好地帮助我们理解代码的底层逻辑。2、在终端使用“gcc -S test.cpp -o test.s”命令进行反汇编(其中test.cpp为你当前的cpp文件名, test.s为输出的反汇编文件名)1、先在VScode中写好c++代码,并保证能编译通过(自己运行或者编译一下)发现左侧文件栏新出现一个test.s。原创 2022-09-07 09:44:10 · 6059 阅读 · 2 评论 -
static静态成员变量
对象的内存中包含了成员变量,不同的对象占用不同的内存,这使得不同对象的成员变量相互独立,它们的值不受其他对象的影响。例如有两个相同类型的对象 a、b,它们都有一个成员变量 m_name,那么修改 a.m_name 的值不会影响 b.m_name 的值。共享数据的典型使用场景是计数,以前面的 Student 类为例,如果我们想知道班级中共有多少名学生,就可以设置一份共享的变量,每次创建对象时让该变量加 1。static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。原创 2022-09-05 10:23:35 · 300 阅读 · 0 评论 -
函数指针(函数作为参数传递给其他函数)
函数也有地址,函数的地址是存储其机器码的内存的开始的地址,并且。因此我们可以将函数作为参数传递给其他函数。正如python中可以将函数轻易的传递给其他函数一样,但是C++中形式上会复杂一些。...原创 2022-08-31 21:05:05 · 3629 阅读 · 1 评论 -
函数和二维数组
如果将二维数组作为参数传递给函数,那么在函数的参数声明中必须指明数组的列数,数组的行数没有太大关系,可以指定也可以不指定。因为函数调用时传递的是一个指针,它指向由行向量够成的一维数组。这里与一维数组一样,虽然我们传入的是数组的指针,但是我们同样可以用正常数组的方式访问其元素,而不需要解引用。data是一个数组名,该数组有三个元素,每一个元素为一个数组。二维数组作为参数时,其数组名被视为其地址,因此和一维数组一样,其相应的形参是一个指针。其中参数size指定二维数组的行数。假如我们有一个二维数组data。..原创 2022-08-31 11:35:02 · 2495 阅读 · 0 评论 -
const与指针
定义指针有一个巧妙的理解方法:从右往左读!原创 2022-08-29 21:23:22 · 343 阅读 · 0 评论 -
文本文件操作
C++中文本文件操作主要是通过fstream头文件以及其中的ifstream对象以及ofstream对象首先,我们在使用ifstream对象以及ofstream对象时必须将其与文件关联起来来实例化对象比如这样实例化一个outFile对象,这个对象代表这你对文本文件要进行的一系列操作。其次,ifstream对象、ofstream对象与我们的cin对象和cout对象基本上用法一致,cout、cin的一些操作他们 也有。原创 2022-08-23 22:37:21 · 869 阅读 · 0 评论 -
cin处理用户异常输入
在13行的while的判断语句中 i>fish[i],因为我们fish数组是定义为double型的,所以如果你的输入是字符型等不符合的输入cin>>fish[i]就会返回false,于是这个判断式确保我们的输入是符合要求的!我的猜测是第13行cin>>fish[i]时因为第一个为数字4,所以跳出while循环,然后打印fish#2,然后再次到13行时我们的cin读取的是队列中的@此时执行while循环。原创 2022-08-22 21:58:01 · 648 阅读 · 0 评论 -
基于范围的for循环
C++11新增了一种循环,基于范围的for循环。这简化了一种常见的循环任务:对数组(或容器类,如vector和array)的每个元素执行相同的操作。个人将其类比python中的 for i in [1, 2, 3]:来记忆。关键格式在第七行:for (double x : prices)此时若再对prices数组进行打印会发现数组元素已经改变!这种循环主要用于各种模板容器类。原创 2022-08-20 18:47:18 · 205 阅读 · 0 评论 -
递增/递减运算符和指针
第12行同样的从右往左,先解引用再++,对pt解引用后得到arr[2]的值,再++即将arr[2]的值加一,即arr[2]变成8,因此输出*pt结果应该为8。依然是从右往左看,先执行pt++将指针递增,然后解引用,那么应该是pt指向arr[3],那么x的值应该为arr[3]=10,*pt也应该为10是吧?第9行*++pt,对于这种我们应该从右往左看,即先++pt再解引用!第15行先对pt解引用再++,解引用得到arr[2]的值,再加1,即arr[2]变成9了,因此输出*pt应该为arr[2] = 9!...原创 2022-08-18 23:01:59 · 188 阅读 · 0 评论 -
数组的地址
从输出结果上看,地址加了1*16+4=20!而这正好是我们整个数组的长度(short两个字节*10个元素)!因此这证明了数组名tell与对数组名取地址数值是一样,但是意义是完全不一样的!我们知道,数组名可以看作是数组首个元素的地址。但是,如果我们对数组名取地址呢?对数组名取地址时,数组名不会解释为数组首个元素的地址,而是整个数组的地址!所以在第三行我们输出地址,第5行我们将pas指针加1。在下面代码中,我们得到的结果是一样的。但是这并不意味着他们是一样的!...原创 2022-08-16 21:35:53 · 991 阅读 · 0 评论 -
C++用new创建动态数组
如果通过像下面这样一般的方法来声明数组,则在程序编译的时候为其分配内存,不管程序最终是否用到这个数组,数组都在那里并占用内存,即静态联编。但是如果使用new,则在运行阶段需要它才进行创建,不需要则不创建,这叫动态联编,这种创建的数组叫做动态数组。并且静态联编必须在写程序时就声明数组长度,而动态联编在运行时才确定数组的长度。我们创建了一个动态数组指针p3后,我们可以通过p3[i]来直接访问数组中的第i个元素。上述代码使得声明一个长为3,类型为double的动态数组。并且动态分配一个空数组是合法的!...原创 2022-08-16 20:57:22 · 9107 阅读 · 0 评论 -
从char到string
string是C++的一个类!原创 2022-08-15 21:46:09 · 406 阅读 · 0 评论 -
C++中cin输入空格
cin.gteline函数有两个参数,第一个是用来存储输入行的数组的名称,第二个参数是要读取的字符数,如果这个参数为20,则函数最多可以读取19个字符,余下的空间用来存储自动在结尾处添加的空字符。cin.get函数与cin.getline函数接受的参数相同,但是由于cin.get不丢弃换行符的原因,我们往往在两个cin.get函数间插入一个空的cin.get表示读取下一个字符!我们还没有输入甜点名称,便跳过cin>>essert直接输出了,并且输出的desert为我们不连续name的空格的后面的字符串!..原创 2022-08-17 21:32:26 · 20616 阅读 · 8 评论 -
C++ 八进制、十进制、十六进制在输出的转换
值得说明的是,标识符hex和oct都位于命名空间std中,因此必须using namespace std;之后或者用std::hex这样的方式才能使用!c++的cout函数可以实现输出在八进制、十进制、十六进制之间的转换。可以看到,第一行输出十进制,第二行输出十六进制,第三行输出八进制!通过标识符hex可以使cout的数字变为十六进制!通过标识符oct可以使cout的数字变为十六进制!cout默认输出为十进制!...原创 2022-08-14 21:09:28 · 2049 阅读 · 1 评论 -
sizeof关键字
sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小。sizeof 运算符可用于获取类、结构、共用体和其他用户自定义数据类型的大小。输出系统自带数据类型大小:结果: 注:这里用了比如__INT__MAX__的符号常量!输出自定义数据类型大小:......原创 2022-08-14 20:45:32 · 568 阅读 · 0 评论 -
任何成员函数的参数都是含this指针的
然后20行调用a.get_data()函数的时候,根据我们上面的说法,任何成员函数的参数都是含this指针的即对象本身(实例化对象)!于是相当于将类a传给函数get_data,即get_data(a);而我们知道,a已经被const修饰过了,但是我们的this指针可不是const型的啊!所以自然没办法这样传递!,这个参数就是对象本身, 即谁调用成员函数, 这个 this 就是谁!这里如果不大清楚,可以看下我这篇博客对python的self实例化指针的叙述!首先19行实例化了一个对象a,并用const修饰!.原创 2022-08-13 18:46:10 · 882 阅读 · 1 评论 -
在函数后面加const
表示函数不可以修改类中的成员!一旦我们想要改变类成员的值便会报错!这样的好处在于:1、提高了代码的可读性,别人看到你这个就知道你这个函数没有改变类成员。2、提高代码的可靠性,即前面说的若想改变改变则会报错!首先,我们要确认一点。在函数后面加const只能在类的成员函数中实现!普通的函数是无法进行这样的操作的!如果我们想克服这种限制,可以选择在想修改的成员变量前用mutable来修饰表示是可修改的!相信大家都见过在函数前面加const的情况,即修饰函数的返回值!那么在函数后面加const的作用是什么呢?...原创 2022-08-13 18:28:25 · 11922 阅读 · 0 评论 -
字符与字符串
字符型变量用于显示单个字符注意1:在显示字符型变量时,用单引号将字符括起来,不要用双引号注意2:单引号内只能有一个字符,不可以是字符串。原创 2022-08-11 10:42:13 · 763 阅读 · 0 评论 -
C++返回this指针
C++的this指针相当于Python中的self,主要看一下下面这段代码:主要难点:1、成员函数PersonAddPerson返回的是*this2、其函数名前有一个&3、加&和去掉&导致p2.age的结果不同自己的理解:1、this指针指向对象,而*this指针解引用就代表这个对象,所以我们使用p2.PersonAddPerson(p1)返回的结果就是*this也就是p2对象2、函数名前加一个&意思是返回引用类型,具体可以看(3条消息) C++中函数名字前的&或*_流楚丶格念的博客-优快云博客_c原创 2022-07-03 23:15:10 · 1586 阅读 · 2 评论 -
深拷贝与浅拷贝
首先,深拷贝和浅拷贝是类的拷贝构造函数里的概念。浅拷贝:即我们的拷贝构造函数进行的简单的赋值拷贝操作深拷贝:在堆区重新申请空间,进行拷贝操作先看下下面这个例子(定义一个类p1,将p1的年龄和身高都拷贝到p2上)其中的身高Height我们放到堆区用指针接收.可以看到,程序正常运行。但是,我们的身高Height是放在堆区是可由程序员自己释放的,所以我们在析构函数中进行释放。 其他的不变,进将析构函数改成上述后,程序运行崩了: 原因:p2拷贝p1的Height指针是将其地址浅拷贝过去了,于是在进行析构原创 2022-06-30 18:43:48 · 162 阅读 · 0 评论 -
类也是一种数据类型
今天在学习C++时,任务是设计一个点类和一个圆类实现判断点和圆的关系。点类很好实现,点的属性就只要设置横坐标和纵坐标就行。圆类的话有圆心和半径两个属性,若是把圆心拆成横坐标和纵坐标两个属性一个增加了多余的属性,第二个这个属性不如圆心直观,但是怎么定义并初始化圆心属性呢,int?double?都不是吧。所以难点就在于貌似没有适合圆心的数据类型。但是类也是一种数据类型(类同样可以作为函数参数,可以值传递,地址传递等):另外在类很多的情况下我们应该将类的声明和实现分别在头文件和源文件中进行。如: 注意这里原创 2022-06-28 17:56:35 · 1261 阅读 · 0 评论 -
数组指针传到函数
首先看一段简单的冒泡排序代码:对于if语句里的三行可能会有点困惑,觉得这样并不能改变实参。事实上,将数组传递给指针时,array[i]就相当于*(array+i),因此是对地址进行操作所以改变实参。写成下面这段等效的代码就好理解了:...原创 2022-06-20 23:17:53 · 868 阅读 · 0 评论 -
C++三目运算符
作用: 通过三目运算符实现简单的判断语法:解释:如果表达式1的值为真,执行表达式2,并返回表达式2的结果;如果表达式1的值为假,执行表达式3,并返回表达式3的结果。示例:结果:原创 2022-06-20 10:31:22 · 2986 阅读 · 0 评论