c++当中的泛型思想以及c++11部分新特性

泛型

泛型就是把数据类型也写成参数,让同一段代码可以安全地处理不同类型,实现代码复用和编译期类型安全。

核心思想就是:不针对具体类型写代码,而是针对任意满足约束的类型T写逻辑。并且能够保证类型安全,在编译期就检查类型是否合法,不会出现错误强制类型转换

c++泛型当中主要通过函数模版和类模版来实现

函数模版

cpp 复制代码
template<typename T> 
T add(T a,T b)
{
   return a+b;
}
//使用
int x=add<int>(1,8);
double y=add<double>(1.1,2.3);

类模板

cpp 复制代码
template<typename T>
class MyStack
{
 private:
   T data[100];
   int top;
 public:
   void push(T val)
   {  
     data[++top]=val;
    }
};
//使用
MyStack<int> st;
   

c++11新特性

智能指针

智能指针会帮助我们管理动态分配的内存,会自动帮助我们释放new出来的内存,避免内存泄漏

std::unique_ptr

独占所有权,最常用

特性:两个unique_ptr不指向同一个资源,所以他禁止复制,只允许转移所有权。

无法左值复制赋值操作,但允许临时右值构造和赋值

左值就是有名字,能赋值,能够反复用的变量

cpp 复制代码
std::unique_ptr<int> p1(new int(10)); 

p1就是左值 ,现在我们来赋值构造

cpp 复制代码
std::unique_ptr<int> p2(p1);

这就是赋值构造,但是编译器不让你干,p1和p2指向同一块内存,析构会重复释放。

复制构造也不行

cpp 复制代码
std::unique_ptr<int> p2;
p2 = p1;  // 报错!

但是允许临时右值的构造赋值

右值就是临时对象,用完就销毁,

允许右值构造,

cpp 复制代码
std::unique_ptr<int> p=std::unique_ptr<int>(10);

允许右值赋值,和转移所有权

cpp 复制代码
std::unique_ptr<int> p1=std::unique_ptr<int>(10);
std::unique_ptr<int> pw;
p2=std::move(p1);

shared_ptr

共享内存

有三条规则:1 拷贝/赋值共享内存,引用计数+1

2指针销毁/置空,引用计数-1

3计数等于0,释放内存

cpp 复制代码
shared_ptr<int> p1=make_shared<int>(10);//计数为1
shared_ptr<int> p2=p1;//计数为2
p1.reset();//重置指针,计数减1
p2.reset();//计数0,自动释放内存

weak_ptr

是弱引用指针,不拥有对象所有权,也不强加计数,作用是打破shared_ptr的循环引用。

weak_ptr除了循环引用问题,还解决了什么问题呢?

1解决了野指针/悬空的问题

cpp 复制代码
A* p=new A();
delete p;
p->func();//此时p还保存着地址,但是对象已经没了。崩溃,访问悬空指针

如果用一个普通指针观察shared_ptr管理的对象

cpp 复制代码
shared_ptr<A> sp=make_shard<A>();
A* raw=sp.get();//拿到裸指针
sp.reset();//对象被销毁
raw->func();//悬空指针,崩溃

weak_ptr会感知对象是否存活,不会变成野指针

cpp 复制代码
shared_ptr<A> sp = make_shared<A>();
weak_ptr<A> wp = sp;

// 检查对象是否还活着
if (!wp.expired()) {
    // 安全访问
}

sp.reset(); // 对象销毁

// 现在 wp 知道对象没了
if (wp.expired()) {
    cout << "对象已销毁,不会访问野指针" << endl;
}

解决this指针不能安全生成shared_ptr的问题

cpp 复制代码
struct A {
    shared_ptr<A> getSelf() {
        return shared_ptr<A>(this); // 灾难!
    }
};

shared_ptr<A> sp1 = make_shared<A>();
auto sp2 = sp1->getSelf();

sp1有一个引用计数块,sp2又有一个引用计数块,两个独立的shared_ptr管理同一个对象,双方都会delete,导致重复释放资源。

std::enable_shared_from_this 底层就是用 weak_ptr 保存 this

右值引用

右值引用专门来绑定右值

cpp 复制代码
int& lref=a;
int&& rref=10;

右值引用的核心作用:实现移动语义

传统拷贝构造函数会做深拷贝,复制堆上的数据,开销极大,并且有些是临时对象,没有必要

cpp 复制代码
string getStr()
{
  return "hello world";
}
string s=getStr();

临时对象马上就要销毁,却还要把数据完整复制一遍,纯纯多余。

右值引用让我们可以接管临时对象的资源,而不是复制

通过右值引用,我们可以实现移动构造和移动赋值

cpp 复制代码
// 拷贝构造(深拷贝,慢)
    MyString(const MyString& other) {
        size_t n = strlen(other.data)+1;
        data = new char[n];
        memcpy(data, other.data, n);
        std::cout << "拷贝构造\n";
    }
    // 移动构造(转移指针,快)
    MyString(MyString&& other) noexcept {
        data = other.data;   // 直接偷指针
        other.data = nullptr;// 原对象置空
        std::cout << "移动构造\n";
    }

lamada表达式

引入的匿名函数,就可以就地定义,就地引用。

lamada表达式的书写格式:

cpp 复制代码
[capture-list](parameters)mutable->return->type{statement}

capture-list捕获列表,决定lamada可以访问哪些外部变量,以什么方式访问

空捕获,不使用任何外部变量

x值捕获,默认只读,不能修改

\&x默认引用捕获,

=默认值捕获用到的所有外部变量

\&默认引用捕获所有用到的外部变量

this类成员函数当中使用,捕获当前对象的this指针,可以访问成员变量或者函数。

\&,=a默认引用捕获,b用值

mutable 让值捕获的变量从const变成可修改

return->type在只有一条语句的时候,可以省略。如果有多条return,并且类型不一样

相关推荐
Cosolar10 小时前
极简智库:快速搭建你的开源项目教程阅读平台,让 docs/ 目录被更多人看见
java·架构·github
nice_lcj52010 小时前
【从零理解 Spring AI · 16】Agent 与工作流:什么该写死,什么该让模型决定
java·人工智能·后端·spring ai·ai应用开发
布莱克60511 小时前
Swift 常量详解:从 let 到编译期优化
服务器·开发语言·ssh·swift·常量·let
北京云帆互联科技11 小时前
云帆培训考试系统更新说明:v9.3.0
java·学习
布莱克60511 小时前
Swift 可选类型(Optionals)详解:从原理到实战
开发语言·安全·ssh·swift·optional·可选类型
老歌老听老掉牙11 小时前
案例 7:二维 Rosenbrock 函数最小值(香蕉函数)
c++·pso
学长毕设12 小时前
基于SpringBoot的景点管理系统-附源码
java·spring boot·后端
Severus_black12 小时前
【C++初阶】Stack、Queue算法题大练兵!
c语言·c++·算法·stl
sxlishaobin13 小时前
Maven Setting详解
java·学习·maven
知守观13 小时前
一个方法两个触发口:反编译 XXL-Job 后,我看清了 inner/job 子包的裸奔现状
java·spring boot·微服务