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 就是函数的一种写法…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...