C++ 学习笔记

yizhihongxing

堆,栈,RAII

堆:分配内存之后需要手动释放,否则,将要造成内存泄漏

  • newdelete操作的是free store
  • mallocfree操作的是heap

new的底层就是malloc

动态获取内存都是在堆中进行的
auto ptr = new std::vector<int>()

智能指针

unique_ptr

独享它所指向的指针,也就是说,同时只有一个unique_ptr指向一个对象,不能多个unique_ptr指向一个对象,
如果说unique_ptr被销毁,那么它所指向的对象也会被销毁

不能进行拷贝复制

shared_ptr

共享他们呢所指向的指针,多个shared_ptr可以同时指向一个相同的对象,在计算机内部采用技术机制来实现
如果有对象关联的话,那么引用计数就会+1,如果智能指针减少,那么就会-1,当变成0,贼会将这个对象进行释放

删除器

在构造函数中第二个删除器就行了

  1. 可以进行拷贝复制

两者区别

unique_ptr 占用资源比较小,所以大多数还是用unique_ptr

字面量

常量是固定的,在程序执行期间不会改变,这些固定的值,就是字面量

左值和右值

左值:一般指一个特定内存的具有名称的值
右值:不指向稳定内存空间地址的匿名值(不据名对象)

通过取地址来判断左值还是右值:
如果能取到地址 就是左值,否则就是右值

x++和++x

x++:右值:首先生成一个x值的临时拷贝。然后才最x递增,最后返回临时复制内容
++x;左值:直接对x递增后马上返回自身,所以说++x是一个左值

注意:字符串常量存储在程序的数据段中,会在加载的时候开辟内存空间,可以使用&来获取字面两的地址

左值就比较强
如果函数返回的是一个值,return x 那么就会变成 右值

左值引用

传入函数的时候用 void swap(int &a,int &b); 加入

注意: 指针运算的时候会发生计算

文件操作

文件流都在<fstream>里面

复合

构造函数由内到外,析构函数由外道内,c++会默认进行执行这些代码,我们只要完成其中的函数
如果自己不写的话,那么就要调用默认的构造函数和析构函数

委托

指针,不同步,外边的函数有了,但是里面的函数有可能没有
什么是委托?
但是

继承

构造函数:先先构造自己的父类,然后再构造自己的
析构函数:先执行父类的析构函数,然后再析构自己

虚函数

non-virtual:不希望子类重新定义他
virtual:希望子类能够重新定义他
pure virtual:希望子类一定要重新定义他

#include <iostream>

class CDocument
{
private:
public:
    void on_file_open()
    {
        std::cout << "你好" << std::endl;
        std::cout << "check file status.." << std::endl;
        std::cout << "open file" << std::endl;
        Serialize();
        std::cout << "close file" << std::endl;
        std::cout << "update all views" << std::endl;

    }
    virtual void Serialize() = 0; // =0 就是纯虚函数 需要子类亲自实现进行实现
};
class CMyDoc : public CDocument
{
private:
public:
    virtual void Serialize()
    {
        std::cout << "CMyDoc::Serialize()" << std::endl;
    }
};
int main()
{
    CMyDoc myDoc;
    myDoc.on_file_open();
}

定义虚函数是允许用基类的指针来调用子类的函数
纯虚函数是为了实现一个接口,起到一个规范的作用,规范是:子类必须继承这个函数

转换函数

class Fraction
{
private:
    int a, b; // a 是分子, b 是分母
public:
    Fraction(int a, int b = 1) : a(a), b(b)
    {}

    // 当做成 double 类型的时候,就会被调用起来
    operator double() const
    {
        return 1.0 * a / b;
    }
};

### explicit

如果加上的话,就是当正确的调用构造函数的时候才会出现,不会隐式的出现这个函数,
所以只要是隐式转换,就会寄了,

`注意`: 这个函数只在构造函数的时候会出现,十分明确当正确的时候才会出现这个函数

```c++
class Fraction
{
private:
    int a;
public:
    Fraction(int a = 1) : a(a)
    {}

    Fraction operator+(const Fraction& other)
    {
        return a + other.a;
    }
};


迭代器

仿函数

不懂

namespace

如果使用using namespace std,那么就会发生冲突,所以说还是用namespace 包起来,然后再使用吧

成员模板

在模板里面的模板,在模板里面发生过变化

函数特化

面对

友元函数

外面的函数不能直接使用private里面的东西,需要加入friend 才能,否则第一个函数的自变量是自己this,

noexcept

void f() noexcept
{

}

保证这个函数不会抛出异常,

Variadic Template (不定参数的模板)

void print()
{

}
template<typename T, typename... Types>
void print(const T& first_arg, const Types& ... args)
{
    std::cout << first_arg << std::endl;
    print(args...);
}

参数可以直接输出递归输出,最后一个是 变成(分解) 1 和 0 ,就会调用第一个print()这个
(这样是处理边界条件)
注意: 应该使用

但是他可以跟这样并存,如

template<typename... Types>
void print(const Types&... args)
{
}

nullptr和 std::nullptr_t

在 c++ 中 还是建议使用 nullptr 使用,否则会有奇异

强制类型转换

  1. static_cast(expression): 编译时

    1. 将一个指向基类的指针转换为指向子类的指针,但是这样的转换不总是安全的
    2. 基本类型之间的转换(int,float,double)之间的转换
  2. const_cast(expression)

    1. 用于去除变量的只读属性
    2. 强制转换的目标类型只能是指针或者引用
  3. reinterpret_cast(expression) 将一个指针重新解释成另一个指针类型

    1. 用于指针类型之间的转换
    2. 用于整数和指针类型之间的强制转换
  4. dynamic_cast(expression):运行时

    1. 有继承关系的类指针之间的转换
    2. 有交叉关系的类指针之间的转换
    3. 具有类型检查的功能
    4. 需要虚函数的支持

防卫式声明

防止重复命名,如果多次引用,那么就会寄了
基本格式是: (注意要规范: 要大写)

#ifndef XXXXX
#define XXXXX

内容

#endif

C++线程

注意一点:
执行类的成员函数的时候,如果不是静态函数的话,那么就要保证创建一个对象,然后才能调用
必须保证对象的生命周期比自线程要长

子线程一定要回收,使用xxx.join()来回收线程

多线程会产生冲突,我们要避免冲突

std::cout是全局对象,当前对象如果全部都在搞这个,那么就寄了

我们要保证访问这个信息数据的时候,要保证线程安全,

所以说我们要用互斥锁来保证

条件变量-生产/消费者模型

当前函数的额度所有

移动构造

RAII 与 智能指针

原文链接:https://www.cnblogs.com/Meteor-Z/p/17271867.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 学习笔记 - Python技术站

(0)
上一篇 2023年4月18日
下一篇 2023年4月18日

相关文章

  • C语言跳转浏览器打开指定URL

    #include <stdlib.h> int main() { // 定义要打开的URL char* url = “https://rjku.gitee.io/”; // 调用系统命令以默认浏览器打开URL char command[100]; sprintf(command, “open %s”, url); system(command);…

    C++ 2023年4月27日
    00
  • 13、c++使用单例模式实现命名空间函数

    本案例实现一个test命名空间,此命名空间内有两个函数,分别为getName()和getNameSpace(); 声明命名空间及函数 namespace test{ const std::string& getName()和(); const std::string& getNameSpace(); } 命名空间内实现单例类 实现一个单例类,…

    C++ 2023年4月24日
    00
  • 内存淘汰策略|页面置换算法对比总结

    在学习【操作系统】 【MySQL】【Redis】后,发现其都有一些缓存淘汰的策略,因此一篇小文章总结一下。 目前还没着笔,初略一想MySQL和操作系统应该都是使用的年轻代和老生代的改进策略,而Redis使用的是随机抽的策略。 MySQL MySQL中存在一个内存缓存池,Buffer Pool。里面存在着控制块和缓存的数据页(当然还有些其他缓存,比如:锁信息、…

    C++ 2023年4月18日
    00
  • 【Qt6】嵌套 QWindow

    在上个世纪的文章中,老周简单介绍了 QWindow 类的基本使用——包括从 QWindow 类派生和从 QRasterWindow 类派生。 其实,QWindow 类并不是只能充当主窗口用,它也可以嵌套到父级窗口中,变成子级对象。咱们一般称之为【控件】。F 话不多讲,下面咱们用实际案例来说明。 这个例子中老周定义了两个类: MyControl:子窗口对象,充…

    C++ 2023年5月2日
    00
  • C++实现一个线程安全的map

    本文是使用ChatCPT生成的,最终的代码使用起来没问题。代码是通过两轮对话完善的,后面把对话合并后跑不出理想效果就没尝试了。 第一轮对话 请求 c++11实现一个线程安全的map,使用方法与std::map保持一致,实现[]运算符 回复 以下是一个简单的线程安全的map实现,可以使用[]运算符来访问和修改map中的元素: //代码省略,后面一起给出 该实现…

    C++ 2023年5月7日
    00
  • 【Visual Leak Detector】核心源码剖析(VLD 2.5.1)

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇对 VLD 2.5.1 源码做内存泄漏检测的思路进行剖析。同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 源码获取 2. 源码文件概览 3. 源码剖析 3.1 通过 inline hook 修补 LdrpCallInitRoutine 3.2 通过 IAT hook 替换内存操…

    C++ 2023年5月11日
    00
  • <五>move移动语义和forward类型转发

    move : 移动语义,得到右值类型forward:类型转发,能够识别左值和右值类型 只有两种形式的引用,左值引用和右值引用,万能引用不是一种引用类型,它存在于模板的引用折叠情况,但是能够接受左值和右值区分左值和右值得一个简单方式就是能不能取地址一个右值一旦有名字那么就变成了左值 #include <iostream> using namespa…

    C++ 2023年5月4日
    00
  • C++容器(vector、deque、list、map)

    (1) vector:将元素置于一个动态数组中,可以随机存储元素(也就是用索引直接存取)。 数组尾部添加或删除元素非常迅速。但在中部或头部就比较费时。 *代码演示:* 取:at在下标越界时会抛出异常,我们能捕获异常进行处理;而[]下标越界会让程序直接终止; 构造函数: cbegin, cend, crbegin, crend返回的是常量迭代器,不能通过迭代器…

    C++ 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部