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

c++11特性与c++17特性

1、自动类型推导auto

// C++11
auto func1() -> int // 需要指定返回值类型
{return 10;
}auto func2() -> std::function<void()>
{auto lambda = []() { };return lambda;
}// c++17
// 之后无需指定返回值类型
auto func1()
{return 10;
}auto func2()
{auto lambda = []() { };return lambda;
}

lambda

// C++11
class Any {
public:Any() { printf("%s()\n", __func__); }~Any() { printf("%s()\n", __func__); }void print() const { printf("%s()\n", __func__); }auto exec() -> std::function<void()>{auto lambda = [this](){this->print();};return lambda;}};auto get() -> std::function<void()>
{Any any;return any.exec();
}int main(int argc, char **argv)
{get()(); // 调用一个已经析构对象的this指针会出现SIGSEGVreturn 0;
}// C++17
class Any {
public:Any() : this_e(this) { printf("%s() this = %p\n", __func__, this); }Any(const Any &other) { printf("%s(const Any &other)\n", __func__); }~Any() { printf("%s()\n", __func__); }void print() const { printf("%s() this = %p\n", __func__, this); }void print_nonconst() { printf("%s()\n", __func__); }auto exec() -> std::function<void()>{auto lambda = [*this](){// 此时*this是const Any类型, 会调用一次拷贝构造, 当不存在拷贝构造时无法捕获*thisassert(this != this_e); // 由于拷贝构造不会修改this_e的值,故this_e还保留着之前对象的地址this->print(); // 同样可以使用this(但只能调用const属性的函数), 此时的this是*this新创建的Any的地址// 通过const_cast来消除const,从而调用非const属性的函数const_cast<Any *>(this)->print_nonconst();};return lambda;}void *this_e;
};/*** c++11无法捕获*this,导致在get()函数返回的lambda在main函数调用时会崩溃* * c++17后可以捕获*this,以获取对象的拷贝*/
auto get() -> std::function<void()>
{Any any;return any.exec();
}int main(int argc, char **argv)
{get()();return 0;
}

结构化绑定

// C++17
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <string>
#include <map>struct Node
{int size;char buffer[128];
};Node &get()
{static Node node;node.size = 10;strncpy(node.buffer, "Hello World", sizeof(node.buffer));printf("node.buffer = %p\n", node.buffer);return node;
}void func()
{std::map<std::string, int> map;map["Hello"] = 100;map["World"] = 200;// 在c++17之前需要声明iterator, 通过iterator访问for (const auto &[key, val] : map) {std::cout << "key = " << key << ", value = " << val << std::endl;}
}int main(int argc, char **argv)
{// 此处声明时需与对象的元素个数一致,且按照元素顺序声明// 可以是auto(拷贝), auto &(引用), const auto &(常量引用)const auto &[size, buffer] = get();std::cout << "size = " << size << ", buffer = " << buffer << std::endl;printf("main() buffer = %p\n", buffer);func();return 0;
}

聚合体

#include <iostream>
#include <string>struct Base {Base(const std::string &_s, int _l) : str(_s), len(_l) { }std::string str;int len;
};struct Other : public Base {bool valid;
};int main(int argc, char **argv)
{{// 构造函数Base b("hello", 5);}{// 聚合体初始化Base b = {"hello", 5};Base b_{"hello", 5}; // C++11之后可以省略等号// 一般情况下不建议使用如下方式初始化,当成员增多时这种写就会生涩难懂且繁琐Other o{{"hello", 5}, true}; // C++17之后支持初始化基类(gcc和msvc1920不支持省略基类的大括号)// 但聚合体初始化常可以用来初始化一些带有默认值的静态对象// QT的源代码中存在许多聚合体初始化// 比如 QHashData::shared_null}return 0;
}
/*** 聚合体初始化需要满足* 1、子类和父类成员需得是public* 2、子类父类都没有虚函数*/

新增属性

[[fallthrough]]
[[nodiscard]]
[[maybe_unused]]

if constexpr

编译期如果满足条件,则只对if的内容进行编译,省去else的编译,反之只编译else内容

template <bool flag>
const char *getDefaultPath()
{const char * path;if constexpr(flag) {path = "/default/ptah";} else {path = "/other";}return path;
}int main(int argc, char **argv)
{getDefaultPath<true>();return 0;
}// g++ -S test.cc -o test.s -std=c++17
	.file	"test.cc".text.globl	main.type	main, @function
main:
.LFB1:.cfi_startprocpushq	%rbpmovq	%rsp, %rbpsubq	$16, %rspmovl	%edi, -4(%rbp)movq	%rsi, -16(%rbp)call	_Z14getDefaultPathILb1EEPKcvmovl	$0, %eaxleave.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE1:.size	main, .-main.section	.rodata
.LC0:.string	"/default/ptah".section	.text._Z14getDefaultPathILb1EEPKcv,"axG",@progbits,_Z14getDefaultPathILb1EEPKcv,comdat.weak	_Z14getDefaultPathILb1EEPKcv.type	_Z14getDefaultPathILb1EEPKcv, @function
_Z14getDefaultPathILb1EEPKcv:
.LFB2:.cfi_startprocpushq	%rbpmovq	%rsp, %rbpleaq	.LC0(%rip), %raxmovq	%rax, -8(%rbp)movq	-8(%rbp), %raxpopq	%rbpret.cfi_endproc
.LFE2:.size	_Z14getDefaultPathILb1EEPKcv, .-_Z14getDefaultPathILb1EEPKcv.ident	"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0".section	.note.GNU-stack,"",@progbits

组件库

std::optional<>

class Any {
public:Any() { printf("%s()\n", __func__); }Any(const Any &other) = delete; /// { printf("%s(const Any &other)\n", __func__); }~Any() { printf("%s()\n", __func__); }
};int main(int argc, char **argv)
{// std::optional支持等号运算符,使用等号时会产生一次拷贝// std::optional<Any> opt = Any();// 通过std::make_optional构造的不会产生拷贝std::optional<Any> opt = std::make_optional<Any>();if (opt) { // or opt.has_value()std::cout << "opt.value()" << std::endl;}return 0;
}

std::variant<>

作用类似union,但是比union更加方便。std::variant只包含模板参数中的一个类型的值,当转换为其他值时会抛出异常。
std::variant是一个变参模板类,可以存放更多的类类型,而不仅限于基础类型。

#include <stdio.h>
#include <iostream>
#include <variant>
#include <assert.h>class Any {
public:Any() { printf("%s()\n", __func__); }Any(const Any &other) { printf("%s(const Any &other)\n", __func__); }~Any() { printf("%s()\n", __func__); }
};int main(int argc, char **argv)
{std::variant<std::string, Any> var_union("hello");assert(0 == var_union.index());const std::string &val = std::get<0>(var_union); // 编译期代码,index()属于运行期,所以不能用index替换0std::cout << val << std::endl;try {const Any &any = std::get<Any>(var_union);assert(true && "never reach here");} catch (...) {std::cout << "catch exception\n";}var_union = Any();assert(1 == var_union.index());return 0;
}

std::any

std::any可以储存任何值的类型,下面以360开源的代码为例

#include <typeinfo>
#include <utility>
#include <assert.h>
// 其核心是Placeholder, 并且运用到了RTTI技术来做安全的类型转换
namespace eular {
// NOTE: class Any need the copy structure
class Any {
public:Any() : content_(nullptr) {}~Any() {if (content_) {delete content_;}}template<typename ValueType>explicit Any(const ValueType& value): content_(new Holder<ValueType>(value)) {}Any(const Any& rhs): content_(rhs.content_ ? rhs.content_->clone() : nullptr) {}public:Any& swap(Any& rhs) {std::swap(content_, rhs.content_);return *this;}template<typename ValueType>Any& operator=(const ValueType& rhs) {Any(rhs).swap(*this);return *this;}Any& operator=(const Any& rhs) {Any(rhs).swap(*this);return *this;}bool empty() const {return !content_;}const std::type_info& type() const {return content_ ? content_->getType() : typeid(void);}template<typename ValueType>ValueType operator()() const {if (getType() == typeid(ValueType)) {return static_cast<Any::Holder<ValueType>*>(content_)->held_;} else {return ValueType();}}protected:class PlaceHolder {public:virtual ~PlaceHolder() {}public:virtual const std::type_info& getType() const = 0;virtual PlaceHolder* clone() const = 0;};template<typename ValueType>class Holder : public PlaceHolder {public:Holder(const ValueType& value): held_(value) {}virtual const std::type_info& getType() const {return typeid(ValueType);}virtual PlaceHolder* clone() const {return new Holder(held_);}ValueType held_;};protected:PlaceHolder* content_;template<typename ValueType>friend ValueType* any_cast(Any*);
};template<typename ValueType>
ValueType* any_cast(Any* any) {if (any && any->getType() == typeid(ValueType)) {return &(static_cast<Any::Holder<ValueType>*>(any->content_)->held_);}return nullptr;
}template<typename ValueType>
const ValueType *any_cast(const Any* any) {return any_cast<ValueType>(const_cast<Any *>(any));
}template<typename ValueType>
ValueType any_cast(const Any& any) {const ValueType *result = any_cast<ValueType>(&any);assert(result);if (!result) {return ValueType();}return *result;
}

std::shared_mutex

读写锁

std::string_view

std::string_view对指向的内容是只读的,其操作是对指针的偏移,所以性能比std::string高

std::filesystem

具体可查看cppreference的filesystem

http://www.lryc.cn/news/15627.html

相关文章:

  • Redis02: Redis基础命令
  • MDK的HardFault硬件异常和NMI异常原因总结
  • 视频图像质量诊断
  • make、Makefile项目自动化构建工具
  • Linux系统之Uboot、Kernel、Busybox思考之一
  • CCNP350-401学习笔记(401-450题)
  • 一文带你看透前端世界里的日期时间,对就是Date
  • 易基因|RRBS单碱基绘制580种动物的基因组规模DNA甲基化谱:Nature子刊
  • 面试官:能用JavaScript手写一个bind函数吗
  • 美国拟发布纽扣电池或硬币电池安全标准和通知要求ANSI C18. 3M
  • 双因素方差分析
  • [ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341)
  • 「TCG 规范解读」第8章 TPM工作组 TPM 1.2中 SHA1的使用
  • 熵权法计算权重
  • redis实现用户签到,统计活跃用户,用户在线状态,用户留存率
  • MySQL中有多少种索引?索引的底层实现原理
  • LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
  • 【Java闭关修炼】MyBatis-接口代理的方式实现Dao层
  • 2022年网络安全政策态势分析与2023年立法趋势
  • 使用vmware制作云平台redhat7.9镜像模板
  • OpenCV基础(28)使用OpenCV进行摄像机标定Python和C++
  • APB总线详解及手撕代码
  • 【Linux/Windows】源文件乱码问题解决方法总结
  • Python 四大主流 Web 编程框架
  • 学UI设计,可以向哪些方向发展?该怎么学?
  • 【C++】初识CC++内存管理
  • Nacos快速使用指南
  • 复旦发布国内首个类ChatGPT模型MOSS,和《流浪地球》有关?
  • 国家级高新区企业主要经济指标(2012-2021年)
  • SpringBoot2核心技术-核心功能【05、Web开发】