当前位置: 首页 > news >正文

Professional C++学习记录

内存管理

理解内存

下面的代码在上面创建了初始化为nullptr的变量ptr,然后为ptr指向堆上的内存。

int* ptr { nullptr };
ptr = new int;或者int* ptr { new int };


虽然ptr指向堆上的内存,但是ptr仍然位于栈上。
注意:指针只是变量,可以存在于堆上或者栈上。而动态内存总是分配在堆上

下面的代码段代码首先声明了一个指向整型指针的指针作为变量 handle,动态地分配足够的内存来存储一个指向整型的指针,并将指向新内存的指针存储在 handle 中。接下来,内存 (*handle)
分配了一个指向另一个足够大的动态内存区域的指针,该区域可以存储整数。

int** ptr {nullptr};
ptr = new int*;
*ptr = new int;
  • ptr 接受的是 new int* 返回的 一个 int** 类型的指针
  • *ptr 接受 new int 的返回值 int*(指向整数的指针)
  • ptr 是指向int* 型变量 的指针
  • *ptr 是指向整型变量的指针
  • **ptr 是整形变量的值

delete *handle;  // 释放 0x3000 的整型数据
delete handle;   // 释放 0x2000 的指针内存
handle = nullptr;  // 安全重置

分配和释放

malloc&free和new&delete的主要区别

new不仅分配内存,还会构造对象
malloc只是为指定的大小分配了一块内存,不知道也不关心对象
delete会调用对象的析构函数,free不会调用
malloc&free是函数 new&delete是操作符

数组内存的分配与释放

简单的一个Simple类

class Simple
{
public:Simple() {std::cout << " Simple construct function..."<< std::endl;}~Simple() {std::cout << " Simple destory construct function..."<< std::endl;}
};

下面这种创建方式相当于在栈上创建了一个Simple* 类型的变量 mySimpleArray
它指向了在堆上的四块内存区域。
对象数组

    Simple* mySimpleArray = new Simple[4];delete[] mySimpleArray;mySimpleArray = nullptr;

指针数组,每个指针指向了一个对象。

const std::size_t s = 4;Simple** mySimpleArray1 = new Simple*[s];
for(int i = 0; i < s; ++i) {mySimpleArray1[i] = new Simple();
}
for(int i = 0; i < s; ++i)
{delete mySimpleArray1[i];mySimpleArray1[i] = nullptr;
}delete[] mySimpleArray1;
mySimpleArray1 = nullptr;

二维数组

char** board = new char*[size];char ** allocateCharacterBoard(size_t xDimension , size_t yDimension) 
{char ** myArray = char* [xDimension];for(int i = 0; i < xDimension; ++i){myArray[i] = new char[yDimension];}return myArray;
}

数组指针二象性

数组会自动退化成指针。但并非所有的指针都是数组。
int *ptr = {new int};

内存泄漏

内存分配后没有及时释放
比如创建一个对象

Simple * originPoint = new Simple();

调用函数

void func(Simple * &outsimplePoint)

当你delete originPoint的时候,删除的是outsimplePoint而不是originPoint。

双重释放

当一个指针被释放之后。该指针关联的内存,就有可能在程序其他地方使用,现在它是一个悬空指针,当你再次释放该指针的时候,就有可能释放掉程序其他的地方的内存。
正确做法:应该在释放指针之后,将它置为空

智能指针

weak_ptr

1.weak_ptr 不拥有资源,用来确定关联的shared_ptr资源是否释放。
2.注意:
• 使用 weak_ptr 实例上的 lock() 成员函数,该函数返回一个 shared_ptr。如果在此期间关联的 shared_ptr 已经释放,返回的 shared_ptr 将为 nullptr。
• 创建一个新的 shared_ptr 实例,并将 weak_ptr 作为 shared_ptr 构造函数的参数传递。如果关联的 shared_ptr 已经释放,这将抛出 std::bad_weak_ptr 异常
要访问对象,必须将weak_ptr转换为shared_ptr(使用lock()成员函数),如果对象还存在,则获得一个有效的shared_ptr,否则返回空的shared_ptr

解决循环引用问题

class Child;
class Parent
{
public:std::shared_ptr<Child> child;~Parent();
};
class Child
{
public:std::shared_ptr<Parent> parent;~Child();
};int main()
{auto parent = std::make_shared<Parent>();auto child = std::make_shared<Child>();parent->child = child;child->parent = parent; // 循环引用
}// 只需要
class Child
{
public:std::weak_ptr<Parent> parent;~Child();
};

类和对象

拷贝赋值和移动赋值

Person& operator=(Person&& p)
Person& operator=(const Person& p) noexcept

拷贝赋值:把另一个对象的内容复制*this,源对象保持不变(语义上)。

移动赋值:把另一个对象的资源窃取/接管*this,源对象被置为“已搬走(moved-from)”的可用但未规定状态,从而避免昂贵的复制。

继承

静态绑定(早期绑定)

在C++中编译一个类时,会创建一个二进制对象,其中包含类的所有成员函数。函数非虚的时候,根据编译时类型,直接在调用成员函数地方硬编码。

虚函数表

有一个或多个虚函数的类都有一个虚函数表。该类的每个实例都包含一个指向该vtable的指针。

动态绑定(晚期绑定)

vtable包含指向虚成员函数实现的指针,当在指向或引用对象的指针或引用上调用成员函数时,会跟随其vtable指针,并根据运行时对象的实际类型调用对应的成员函数。

class Base
{public:virtual void func1();virtual void func2(); void test();
};class Derived : public Base
{public:void func1() override;void test();
};

虚析构函数

析构函数应该为虚。如果析构函数不为虚,很容易导致对象销毁时内存没有释放。只有在标记为 final 的类中,才可以让其析构函数设置为非虚。

```c++
class Base
{public:virtual ~Base();
};class Derived : public Base
{public:~Derived();
};

基类析构函数声明为虚函数,根据虚函数表,从派生类到基类的顺序一次调用析构函数。
如果不是,析构函数的选择编译时决定的。

构造顺序

基类->类的非静态数据成员->类

public Something
{public:Something() { std::cout << "2\n"; }
};class Base
{public:Base() { std::cout << "1\n"; }
};class Derived : public Base
{public:Derived() { std::cout << "3\n"; }private:Something _some; 
};

结果:1,2,3

析构顺序

类->以与构造相反的顺序销毁类的数据成员->基类

上下转换

派生类转基类
会丢失自己所有的特性,只包含父类的特性。会产生切片。

Derived myDerived;
Base myBase { myDerived}; // 产生切片Base &myBase { myDerived}; // 不产生切片

基类转派生类
这是一种非常不好的设计。尽量使用 dynamic_cast()。
使用对象的内置类型来拒绝不合理的转换。这种内置类型位于vtable上,所以dynamic_cast只对具有vtable的对象有效。
指针上转换失败,返回nullptr;
对象引用上转换失败,抛出std::bad_cast异常;

http://www.sczhlp.com/news/44430/

相关文章:

  • 8.27模拟赛题解
  • 在WSL中配置Ollama和局域网访问
  • 做宣传网站的公司seo排名优化工具推荐
  • 网站访问速度网络营销推广要求
  • 宁德工程建设监督网站手机百度2020最新版
  • 做网站要主机还是服务器建站公司最新报价
  • 网站开发日志网络宣传策划方案
  • 网站注册主机网站推广排名
  • 网站动画用什么做的营销推广活动策划书模板
  • 燕郊网站建设公司杭州做网站的公司排行
  • 党委门户网站建设意义飓风seo刷排名软件
  • 长沙做网站的有哪些整站关键词快速排名
  • 武清做网站的短视频剪辑培训班多少钱
  • vscode、cursor安装离线插件
  • 数据结构C++ 二分搜索
  • 南通网站建设推广seo排名点击软件推荐
  • 如何做自己的网站赚钱东莞网络推广平台
  • 西宁企业网站建设开发百度在线客服中心
  • 手机优化不足80怎么办seo是什么seo怎么做
  • 汕头选择免费网站优化软文推广公司有哪些
  • sh域名做的好的网站百度地图关键词优化
  • 嘉兴企业做网站淘宝seo搜索优化工具
  • 做棋牌网站合法seo方法图片
  • 从Excel向word写数据
  • 高端建站模版百度搜索引擎入口官网
  • 政府网站集约化试点工作建设背景什么叫软文推广
  • 建设银行信用卡申请网站十大营销策划公司排名
  • 廊坊哪家公司做网站宁波谷歌seo推广公司
  • 爱奇艺的网站是用什么做的今日国际新闻最新消息事件
  • 做网站导出用什么色彩模式抖音seo点击软件排名