C++相关闲碎记录(2)
1、误用shared_ptr
int* p = new int;
shared_ptr<int> sp1(p);
shared_ptr<int> sp2(p); //error
// 通过原始指针两次创建shared_ptr是错误的shared_ptr<int> sp1(new int);
shared_ptr<int> sp2(sp1); //ok
如果对C++相关闲碎记录(1)中记录的shared_ptr的使用例子修改为如下:父类添加孩子的shared_ptr时调用下面这个函数来实现,同样会出现问题:
class Person {
public:string name;shared_ptr<Person> mother;shared_ptr<Person> father;vector<weak_ptr<Person>> kids; //使用weak_ptrPerson(const string& n, shared_ptr<Person> m = nullptr,shared_ptr<Person> f = nullptr) :name(n), mother(m), father(f) {}~Person() {cout << "delete " << name << endl;}void setParentAndTheirKids(shared_ptr<Person> m = nullptr, shared_ptr<Person> f = nullptr) {mother = m;father = f;if (m != nullptr) {m->kids.push_back(shared_ptr<Person>(this)); //error// 为什么这里会报错,因为this所指的对象已经有一个shared_ptr了,再通过这种方式创建shared_ptr就会报错,因为会重新开启一个拥有者团队}if (f != nullptr){f->kids.push_back(shared_ptr<Person>(this)); //error}}
};shared_ptr<Person> initFamily(const string& name) {shared_ptr<Person> mom(new Person(name + "'s mom"));shared_ptr<Person> dad(new Person(name + "'s dad"));shared_ptr<Person> kid(new Person(name));kid->setParentAndTheirKids(mom, dad);return kid;
}
使用enable_shared_from_this<Person>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;class Person : public enable_shared_from_this<Person> {public:string name;shared_ptr<Person> mother;shared_ptr<Person> father;vector<weak_ptr<Person>> kids; // weak pointer !!!Person (const string& n): name(n) {}void setParentsAndTheirKids (shared_ptr<Person> m = nullptr,shared_ptr<Person> f = nullptr) {mother = m;father = f;if (m != nullptr) {m->kids.push_back(shared_from_this());}if (f != nullptr) {f->kids.push_back(shared_from_this());}}~Person() {cout << "delete " << name << endl;}
};shared_ptr<Person> initFamily (const string& name)
{shared_ptr<Person> mom(new Person(name+"'s mom")); shared_ptr<Person> dad(new Person(name+"'s dad")); shared_ptr<Person> kid(new Person(name)); kid->setParentsAndTheirKids(mom,dad); return kid;
}int main()
{shared_ptr<Person> p = initFamily("nico");cout << "nico's family exists" << endl;cout << "- nico is shared " << p.use_count() << " times" << endl;cout << "- name of 1st kid of nico's mom: " << p->mother->kids[0].lock()->name << endl;p = initFamily("jim");cout << "jim's family exists" << endl;
}
shared_ptr各种操作:
shared_ptr<void> sp(new int);
shared_ptr<int>(static_cast<int*>(sp.get())) //error
static_pointer_cast<int*>(sp)std::unique_ptr<int> up = new int; //error
std::unique_ptr<int> up(new int); // ok
unique_ptr不必一定拥有对象,也可以是empty。
std::unique_ptr<std::string> up;
可以赋值为nullptr或者调用reset
up = nullptr;
up.reset();
unique_ptr可以调用release(),释放所拥有的对象,并将所有权交给调用者。
std::unique_ptr<std::string> up(new std::string("nico"));
std::string* sp = up.release();
2、转移unique_ptr的拥有权
std::string* sp = new std::string("hello");
std::unique_ptr<std::string> up1(sp);
std::unique_ptr<std::string) up2(sp); //error up1 and up2 own same datastd::unique_ptr<std::string[]> up(new std::string[10]); //ok
此偏特化不再提供操作符*和->,而提供[]操作符,访问array中的一个对象时,使用[]std::cout << *up << std::endl; //error
std::cout << up[0] << std::endl; //ok
指定自定义删除器:通过类的方式指定
class ClassADeleter {
public:void operator() (ClassA* p) {std::cout << "call delete for ClassA object" << std::endl;delete p;}
};std::unique_ptr<ClassA, ClassADeleter> up(new ClassA());
如果是个函数或者lambda,必须声明deleter的类型为void(*)(T*)或者std::function<void(T*)>,要不就使用decltype,例如要为array of int指定自己的deleter,并以lambda形式呈现:
std::unique_ptr<int, void(*)(int*)> up(new int[10], [](int* p) {delete []p;});std::unique_ptr<int, std::function<void(int*)>> up(new int[10], [](int* p) {delete []p;});或者
auto l = [](int*) {delete [] p;};
std::unique_ptr<int, decltype(l)>> up(new int[10], l);
为了避免传递function pointer 或者lambda 时必须指明deleter的类型,你可以使用alias template
template<typename T>
using uniquePtr = std::unique_ptr<T, void(*)(T*)>;uniquePtr<int> up(new int[10], [](int* p) {delete [] p;});
unique_ptr各种操作:
3、numeric_limits<>
#include <iostream>
#include <limits>
#include <string>
using namespace std;int main()
{// use textual representation for boolcout << boolalpha;// print maximum of integral typescout << "max(short): " << numeric_limits<short>::max() << endl;cout << "max(int): " << numeric_limits<int>::max() << endl;cout << "max(long): " << numeric_limits<long>::max() << endl;cout << endl;// print maximum of floating-point typescout << "max(float): "<< numeric_limits<float>::max() << endl;cout << "max(double): "<< numeric_limits<double>::max() << endl;cout << "max(long double): "<< numeric_limits<long double>::max() << endl;cout << endl;// print whether char is signedcout << "is_signed(char): "<< numeric_limits<char>::is_signed << endl;cout << endl;// print whether numeric limits for type string existcout << "is_specialized(string): "<< numeric_limits<string>::is_specialized << endl;
}
4、type trait的使用
#include <iostream>
#include <limits>
#include <string>
using namespace std;// type trait
template <typename T>
void foo_impl(T val, true_type) {std::cout << "Integer" << std::endl;
}template <typename T>
void foo_impl(T val, false_type) {std::cout << "not Integer" << std::endl;
}template <typename T>
void foo(T val) {foo_impl(val, std::is_integral<T>());
}int main()
{double d_a = 1.2;long long int ll_b = 33333;foo(d_a);foo(ll_b);
}输出:
not Integer
Integer
类型判断工具
用以阐明class细节的trait
#include <iostream>
#include <limits>
#include <type_traits>
using namespace std;int main()
{std::cout << boolalpha << is_const<int>::value << endl; //falsestd::cout << boolalpha << is_const<const volatile int>::value << endl; //truestd::cout << boolalpha << is_const<int* const>::value << endl; //truestd::cout << boolalpha << is_const<const int*>::value << endl; //falsestd::cout << boolalpha << is_const<const int&>::value << endl; //falsestd::cout << boolalpha << is_const<int[3]>::value << endl; //falsestd::cout << boolalpha << is_const<const int[3]>::value << endl; //truestd::cout << boolalpha << is_const<int[]>::value << endl; //falsestd::cout << boolalpha << is_const<const int[]>::value << endl; //truereturn 0;
}
指向const类型的非常量指针或者引用,并不是一个常量,尽管内含元素是常量,例如const int* 并不是常量,只是描述指针所指向的这个变量是常量类型,但是指针本身可以重新指向新的变量。
用以检测copy和move语义的那些个trait,只检测是否相应的表达式为可能,例如一个带有copy构造函数的(接受常量实参)但没有move构造函数的类型,仍然是move constructible.
用以检验类型关系的trait
int main()
{std::cout << boolalpha << is_assignable<int, int>::value << endl; //falsestd::cout << boolalpha << is_assignable<int&, int>::value << endl; //truestd::cout << boolalpha << is_assignable<int&&, int>::value << endl; //falsestd::cout << boolalpha << is_assignable<long&, int>::value << endl; //truestd::cout << boolalpha << is_assignable<int&, void*>::value << endl; //falsestd::cout << boolalpha << is_assignable<void*, int>::value << endl; //falsestd::cout << boolalpha << is_assignable<const char*, std::string>::value << endl; //falsestd::cout << boolalpha << is_assignable<std::string, const char*>::value << endl; //truestd::cout << boolalpha << is_constructible<int>::value << endl; //truestd::cout << boolalpha << is_constructible<int, int>::value << endl; //truestd::cout << boolalpha << is_constructible<long, int>::value << endl; //truestd::cout << boolalpha << is_constructible<int, void*>::value << endl; //falsestd::cout << boolalpha << is_constructible<void*, int>::value << endl; //falsestd::cout << boolalpha << is_constructible<const char*, std::string>::value << endl; //falsestd::cout << boolalpha << is_constructible<std::string, const char*>::value << endl; //truestd::cout << boolalpha << is_constructible<std::string, const char*, int, int>::value << endl; //truereturn 0;
}
5、类型修饰符
#include <iostream>
#include <limits>
#include <type_traits>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;int main()
{typedef int T;typedef add_const<T>::type A; //const inttypedef add_lvalue_reference<T>::type B; //int&typedef add_rvalue_reference<T>::type C; //int&&typedef add_pointer<T>::type D; //int*typedef make_signed<T>::type E; //inttypedef make_unsigned<T>::type F; //unsigned inttypedef remove_const<T>::type G; //inttypedef remove_reference<T>::type H; //inttypedef remove_pointer<T>::type I; //intstd::cout << boolalpha << is_const<A>::value << std::endl;// 查看完整类型std::cout << abi::__cxa_demangle(typeid(A).name(),0,0,0 ) << std::endl;std::cout << typeid(B).name() << std::endl;std::cout << "A is same const int ?" << boolalpha << is_same<const int, A>::value << std::endl;std::cout << "B is same int& ?" << boolalpha << is_same<int&, B>::value << std::endl;typedef const int& T1;typedef add_const<T1>::type A1; // const int&typedef add_lvalue_reference<T1>::type B1; //const int&typedef add_rvalue_reference<T1>::type C1; //const int& (yes, lvalue remains lvalue)typedef add_pointer<T1>::type D1; //const int*// typedef make_signed<T1>::type E1; //undefined behavior// typedef make_unsigned<T1>::type F1; //undefined bahaviortypedef remove_const<T1>::type G1; //const int&typedef remove_reference<T1>::type H1; //const inttypedef remove_pointer<T1>::type I1; //cosnt int&std::cout << "A1 is same const int& ?" << boolalpha << is_same<const int&, A1>::value << std::endl;std::cout << is_const<A1>::value << std::endl;std::cout << "G1 is same const int& ?" << boolalpha << is_same<const int&, G1>::value << std::endl;return 0;
}
指向某常量类型的reference本身并不是常量,所以不可以移除const,add_pointer<>必然包含使用remove_reference<>,然而make_signed<>和make_unsigned<>必须是整型,枚举型,bool除外,所以传入引用会导致不明确的行为。add_lvalue_reference<>把一个rvalue reference转换为一个lvalue reference,然而add_rvalue_reference<>并不会把一个lvalue reference转换为一个rvalue reference.
6、其他type trait
#include <iostream>
#include <limits>
#include <type_traits>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;int main()
{std::cout << rank<int>::value << std::endl; //0std::cout << rank<int[]>::value << std::endl; //1std::cout << rank<int[3]>::value << std::endl; //1std::cout << rank<int[][4]>::value << std::endl; //2std::cout << rank<int[3][4]>::value << std::endl; //2std::cout << extent<int>::value << std::endl; //0std::cout << extent<int[]>::value << std::endl; //0std::cout << extent<int[3]>::value << std::endl; //3std::cout << extent<int[][4]>::value << std::endl; //0std::cout << extent<int[3][3]>::value << std::endl; //3std::cout << extent<int[][3], 1>::value << std::endl; //3std::cout << extent<int[5][6], 1>::value << std::endl; //6std::cout << extent<int[3][4], 2>::value << std::endl; //0typedef remove_extent<int>::type A; //inttypedef remove_extent<int[]>::type B; //inttypedef remove_extent<int[3]>::type C; //inttypedef remove_extent<int[][8]>::type D; //int[8]typedef remove_extent<int[5][6]>::type E; //int[7]typedef remove_all_extents<int>::type F; //inttypedef remove_all_extents<int>::type G; //inttypedef remove_all_extents<int[]>::type H; //inttypedef remove_all_extents<int[5]>::type I; //inttypedef remove_all_extents<int[][9]>::type J; //inttypedef remove_all_extents<int[5][8]>::type K; //intreturn 0;
}
相关文章:

C++相关闲碎记录(2)
1、误用shared_ptr int* p new int; shared_ptr<int> sp1(p); shared_ptr<int> sp2(p); //error // 通过原始指针两次创建shared_ptr是错误的shared_ptr<int> sp1(new int); shared_ptr<int> sp2(sp1); //ok 如果对C相关闲碎记录(1)中记录的shar…...

如何快速搭建一个大模型?简单的UI实现
🔥博客主页:真的睡不醒 🚀系列专栏:深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 💘每日语录:相信自己,一路风景一路歌,人生之美,正在于…...

国家开放大学 平时作业 测试题 训练
试卷代号:1340 古代小说戏曲专题 参考试题(开卷) 一、选择(每题1分,共10分) 1.下列作品中属于唐传奇的是( )。 A.《公孙九娘》 B.《观音作别》 C《碾玉观音》 …...

后端防止重复提交相同数据处理方式(Redis)
使用AOP注解处理接口幂等性,默认禁止同一用户在上次提交未果后10秒内又重复提交 在原先的sameUrlData的注解上进行了copy新建优化,使用redis去setnx的参数视项目使用点而调整,不一定是每个项目都适合这种取参形式。 源码如下: package com…...

最小栈[中等]
优质博文:IT-BLOG-CN 一、题目 设计一个支持push,pop,top操作,并能在常数时间内检索到最小元素的栈。 实现MinStack类: MinStack()初始化堆栈对象。 void push(int val)将元素val推入堆栈。 void pop()删除堆栈顶部的元素。 in…...

Oracle(2-9) Oracle Recovery Manager Overview and Configuration
文章目录 一、基础知识1、User Backup VS RMAN2、Restoring &Recovering DB 还原&恢复数据库3、Recovery Manager Features 管理恢复功能4、RMAN Components RMAN组件5、Repository1: Control File 存储库1:控制文件6、Channel Allocation 通道道分配7、Media Manageme…...

滑动验证码
先上图 代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>滑动验证码</title><style>* {margin: 0;padding: 0;}.box {position: relative;width: 375px;margin: 100px a…...

数据爬取+可视化实战_告白气球_词云展示----酷狗音乐
一、前言 歌词上做文本分析,数据存储在网页上,需要爬取数据下来,词云展示在工作中也变得日益重要,接下来将数据爬虫与可视化结合起来,做个词云展示案例。 二、代码 # -*- coding:utf-8 -*- # 酷狗音乐 通过获取每首歌…...

rkmedia_vi_get_frame_test.c 代码解析
使用示例: 录像: rkmedia_vi_get_frame_test -a /etc/iqfiles/ -I 1 -o 1080.nv12 然后用yuvplayer.exe可以播放。 录像10帧: rkmedia_vi_get_frame_test -a /etc/iqfiles/ -I 1 -o 1080.nv12 -c 10 解析代码: #include <as…...

探究Kafka原理-3.生产者消费者API原理解析
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码、Kafka原理🔥如果感觉博主的文章还不错的话,请ὄ…...

Linux系统iptables扩展
目录 一. iptables规则保存 1. 导出规则保存 2. 自动重载规则 ①. 当前用户生效 ②. 全局生效 二. 自定义链 1. 新建自定义链 2. 重命名自定义链 3. 添加自定义链规则 4. 调用自定义链规则 5. 删除自定义链 三. NAT 1. SNAT 2. DNAT 3. 实验 ①. 实验要求 ②. …...

Openwrt 系统安装 插件名称与中文释义
系统镜像 当时是去官网找对应的,但是作为门外汉,想简单,可以试试这个网站 插件 OpenWrt/Lede全部插件列表功能注释...

[原创]Delphi的SizeOf(), Length(), 动态数组, 静态数组的关系.
[简介] 常用网名: 猪头三 出生日期: 1981.XX.XXQQ: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi…...

C++(20):bind_front
C(11):bind_c11 bind_风静如云的博客-CSDN博客 提供了方法来绑定函数参数的方法。 C20提供了bind_front用于简化这个绑定。 #include <iostream> #include <functional> using namespace std;void func1(int d1, int d2) {cout<<__func__<&l…...

【spring】bean的后处理器
目录 一、作用二、常见的bean后处理器2.1 AutowiredAnnotationBeanPostProcessor2.1.1 说明2.1.2 代码示例2.1.3 截图示例 2.2 CommonAnnotationBeanPostProcessor2.2.1 说明2.2.2 代码示例2.2.3 截图示例 2.3 ConfigurationPropertiesBindingPostProcessor2.3.1 说明2.3.2 代码…...

Centos7安装docker、java、python环境
文章目录 前言一、docker的安装二、docker-compose的安装三、安装python3和配置pip3配置python软链接(关键) 四、Centos 7.6操作系统安装JAVA环境 前言 每次vps安装docker都要看网上的文章,而且都非常坑,方法千奇百怪,…...

简单小结类与对象
/*** Description 简单小结类与对象*/ package com.oop;import com.oop.demo03.Pet;public class Application {public static void main(String[] args) {/*1.类与对象类是一个模版:抽象,对象是一个具体的实例2.方法定义、调用!3.对象的引用…...

ABAP 如何获取内表行的索引值(index) ?
获取索引值 在ABAP中,如果需要获取一个内表中某条记录的索引(index),可以使用 READ TABLE 语句。在 READ TABLE 语句后面的 WITH KEY 子句可以指定搜索条件,如果找到了匹配的记录,系统字段 SY-TABIX 将保存…...

ESP32-Web-Server编程- 使用表格(Table)实时显示设备信息
ESP32-Web-Server编程- 使用表格(Table)实时显示设备信息 概述 上节讲述了通过 Server-Sent Events(以下简称 SSE) 实现在网页实时更新 ESP32 Web 服务器的传感器数据。 本节书接上会,继续使用 SSE 机制在网页实时显…...

vue3 Hooks函数使用及常用utils封装
hooks 是什么 vue3使用了composition API,我们可自定义封装hooks,达到复用,在Vue2中采取的mixins,对mixins而言, hooks更清楚复用功能代码的来源, 更清晰易懂。 简单来说:hooks 就是函数的一种写法…...

matlab 无迹卡尔曼滤波
1、内容简介 略 26-可以交流、咨询、答疑 2、内容说明 无迹卡尔曼滤波 无迹卡尔曼滤波 无迹卡尔曼滤波 3、仿真分析 %该文件用于编写无迹卡尔曼滤波算法及其测试 %注解:主要子程序包括:轨迹发生器、系统方程 % 测量方程、UKF滤波器 %----…...

大脑--学习方法
1.大脑喜欢色彩。平时使用高质量的有色笔或使用有色纸,颜色能帮助记忆。 2.大脑集中精力最多只有25分钟。这是对成人而言,所以学习20到30分钟后就应该休息10分钟。你可以利用这段时间做点家务,10分钟后再回来继续学习,效果会更好…...

4.C转python
1.建立函数: def 函数名(形参): 函数体(记得写缩进) return 返回值(python中可以没有return) 2.调用函数: 函数名(实参) 实参和形参个数相等即可,类型不需要相同 其中接收返回值与C中的差不多 3.如果只是定义而不调用则函数不会执行 4.先定义函数,后调用 5.python中可以…...

YOLOv5项目实战(5)— 算法模型优化和服务器部署
前言:Hello大家好,我是小哥谈。近期,作者所负责项目中的算法模型检测存在很多误报情况,为了减少这种误报情况,作者一直在不断优化算法模型。鉴于此,本节课就给大家详细介绍一下实际工作场景中如何去优化算法模型和进行部署,另外为了方便大家进行模型训练,作者在文章中提…...

JavaScript类型判断:解密变量真实身份的神奇技巧
文章目录 1. typeof运算符2. instanceof运算符3. Object.prototype.toString4. Array.isArray5. 使用constructor属性6. 使用Symbol.toStringTag7. 使用is类型判断库8. 谨慎使用隐式类型转换结语 🎉JavaScript类型判断:解密变量真实身份的神奇技巧 ☆* o…...

MT6893_天玑 1200芯片规格参数介绍_datasheet规格书
天玑 1200(MT6893)是一款专为旗舰级全新5G芯片,它融合了先进的AI、相机和多媒体技术,为用户带来令人惊叹的体验。采用先进的6纳米制程设计,内置各种先进技术。该芯片采用旗舰级的八核CPU架构设计,支持16GB强大的四通道内存以及双通…...

【Android踩过的坑】13.Android Studio 运行成功,但APP没有安装上的问题
【Android踩过的坑】13.Android Studio 运行成功,但APP没有安装上的问题 解决办法: 在app的build.gradle文件下添加以下代码 android {...//android.useNewApkCreatorfalse 在高版本gradle下无效,添加以下代码解决冲突即可packagingOptions…...

redis安装配置
Windows 下 Redis 安装与配置 教程_redis windows-CSDN博客 启动Redis服务 打开cmd窗口,切换到Redis安装路径,输入 redis-server 启动 redis 服务...

企业数字化转型应对传统网络挑战的关键策略
数字化变革正在以前所未有的速度和规模改变着我们的生活和工作方式,使得传统网络架构面临着巨大的挑战。其中包括带宽需求增加、多云应用增加、安全威胁增加以及传统网络设备无法满足需求等问题。 数字化时代需要更高速、更可靠、更安全的网络支持,传统网…...

Java 多线程基础 线程4种创建方式
目录 什么是进程什么是多线程使用多线程的好处使用多线程的应用场景单线程与多线程之间的区别如何理解线程上下文切换使用多线程真的开启越多越好吗线程4种创建的方式1.继承Thread类2.使用Runnable3.使用Callable4.线程池的方式 多线程五种的状态如何优雅的停止一个线程 什么是…...