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,并且类型不一样

相关推荐
智慧地球(AI·Earth)1 小时前
规则引擎实战:Python中re库和pyknow库规则引擎实战教程
开发语言·python·程序人生
梦魇星虹2 小时前
idea Cannot find declaration to go to
java·ide·intellij-idea
小雅痞2 小时前
[Java][Leetcode hard] 42. 接雨水
java·开发语言·leetcode
xfcoding2 小时前
关于代码注释的思考
java
We་ct2 小时前
AI辅助开发术语体系深度剖析
开发语言·前端·人工智能·ai·ai编程
t***5442 小时前
Dev-C++中哪些选项可以设置
开发语言·c++
輕華2 小时前
PyQt5入门实战:安装、QtDesigner设计与PyUIC转换完整指南
开发语言·qt
虹梦未来2 小时前
【开发心得】在SpringBoot体系中正确使用redisConfig
java·spring boot·spring
skiy2 小时前
Spring Framework 中文官方文档
java·后端·spring