小古银的官方网站(完整教程):http://www.xiaoguyin.com/
C++入门教程视频:https://www.bilibili.com/video/av20868986/
目录
这篇说的内容还是构造函数和析构函数,我知道你看到这里会开始有点不耐烦了,怎么这么多构造函数和析构函数,基础太多。其实这个不难,所以不要担心,而且后面还有几种构造函数。再耐心把它学好,写代码将会很有用的。。。大概吧(*・_・)ノ⌒*
但是你想想,你设计一个类给别人用的时候,就是写开源代码的时候,你必须要封装好,别人用的时候才能用得方便用得爽,用得爽了别人就觉得你niubility。ԅ(¯﹃¯ԅ)
default
当类中没有构造函数的时候,编译器就会加一个默认构造函数;当你加了一个构造函数的时候,例如重载的一个构造函数,那么就不会再有默认构造函数。举个例子:
#include <iostream>
class Test
{
public:
Test(int)
{
}
};
int main(void)
{
// 去掉下面注释将会报错
// 因为已经没有了默认构造函数而且也没有无参数的构造函数
// Test test;
return 0;
}
这时候如果需要无参数地创建对象,并且又不需要在构造函数里进行操作,就可以:
基础示例
#include <iostream>
class Test
{
public:
Test(void) = default;
Test(const Test &)
{
}
};
int main(void)
{
Test test;
return 0;
}
基础讲解
构造函数声明后加= default;
,就可以把默认构造函数调出来,而且还可以不用写函数定义。当然,如果你的构造函数里是有操作的,那么它就不是默认构造函数,不能用关键字default
,而且你还是要把它的定义写出来,这样你才能操作。
最后轮到默认析构函数:~Test(void) = default;
。
因为如果需要在析构函数里写代码,那么肯定要写出析构函数;如果不需要在析构函数里写代码,不写的话,编译器也会给加上。所以看上去没什么用处。
如果类用作基类,供其他类继承的话,默认析构函数就有作用了,这时候需要这样写virtual ~Test(void) = default;
。至于为什么这样写,后续教程将会讲解。
基础拓展
关键字default
只能作用在有默认函数的函数上,也就是说,只能用在默认构造函数、默认复制构造函数、默认转移构造函数、默认复制赋值运算符、默认移动赋值运算符和默认析构函数上。
delete
关键字delete
用于删除函数,即如果你调用了删除的函数,编译器编译的时候就会报错。关键字delete
与default
不同,delete
可以用在所有的函数上。
delete
用得最多的情况,还是用在构造函数上。例如,std::unique_ptr
不能复制只能转移,所以std::unique_ptr
的复制构造函数是这样写的:unique_ptr(const unique_ptr &) = delete;
,那么当你尝试复制std::unique_ptr
对象时,编译时就会报错。
当delete
用在其他函数时的用法也是跟上面的一样,只需要在函数声明的后面,分号;
的前面加上= delete
即可。由于函数已经删除,所以你也没有写函数定义的必要了。
巩固练习
完成simple_vector
的push_back()
和pop_back()
。
提示:
push_back()
:先申请m_size + 1
个int
的堆内存并且用临时变量保存,这样可以保证无论m_array
是否保存地址都不会出错。当没有元素时,就不需要复制旧内存的数据了,而且也没有内存可以释放;相反,当有元素时就需要复制旧内存的数据,复制完没什么事就可以把旧内存释放掉。然后把新的数据存放到连续内存的最后,接着把新内存地址赋值给m_array
并且m_size
自增就完事了。
pop_back()
:当本来就没有元素时是不能再删除最后一个元素,这是需要注意的,接着就剩下有元素的情况了。申请新的m_size - 1
个内存,然后将除了最后一个数据的旧数据复制到新内存中,释放旧内存,接着把新内存地址赋值给m_array
并且m_size
自减就完事了。
温馨提示
当调用std::vector
中pop_back()
的时候,由于标准没有规定pop_back()
必须要检测是否有元素,如果此时std::vector
对象没有元素,那么将会引发未定义行为,所以使用std::vector
的pop_back()
时,需要注意容器内是否有元素。这些都是明确写在说明文档里面的,看文档时需要留心。