C 是一门古老的语言, C++在为C 引入了面向对象和泛型,也引入了许多的复杂性,例如多重继承,模板的特化,等等。同时 C++ 本身除了 STL 标准库,缺少高质量的并发和网络软件包,每个C++程序员或多或少都造过大大小小的轮子。

例如我就写过很多 string 处理的函数, 比如 Trim, LowerCase, UpperCase, 等等,还有基于引用计数的智能指针,包装 pthread 函数的线程类,林林总总,各种轮子都要自己和团队手工打造。有时有点成就感,可是显然也拖慢了开发速度,自己的轮子虽然够用,可是并非考虑周全,异常保护不够,经常会挖坑,也让别人踩坑。

所以近年来,逐渐在项目中引入 boost 库来提高开发效率,也从 C++ 98 向 C++11, 14, 17, 乃至 C++ 20 过渡。

在 C++ 11、14、17、20 中我们可以看到很多 boost library 的影子, 例如 boost::shared_ptr, boost::thread , boost::random, 等等。

C++ 11 新特性

改进的对象构造

  • 继承基类的构造函数
  • 默认的成员值
  • 委托构造函数
  • overwrite 关键字
  • final 关键字
  • 统一的初始化 {}

其他语言增强

  • 基于范围的 for 循环
  • long long int 类型 (64位)
  • lambda 函数
  • 移动语义和右值引用
  • 强类型枚举: enum 增加了类型检查
  • 智能指针
  • 原始字符串字面量
  • 静态断言
  • 可变参数模板
  • 改善了右尖括号的处理

新的关键字

  • auto 自动类型推导
  • constexpr: 表达式常量
  • decltype: 声明类型
  • nullptr: 空指针
  • thread_local: 线程局部存储

对 C++ 库的增强

  • stl 容器的列表初始化
  • 随机库
  • 正则表达式库
  • 无序容器(hash)
  • 附加的算法
  • 元组模板
  • 其他的新类型: chrono(时间测量), ratio(有理数分数), complex(复数)

作为一个 Java/C++ 都时常用到的老程序员,委托构造函数,智能指针,lambda 等许多东西都不新鲜,唯独需要重点提到的是右值。

C++ 本来就已经很复杂了,为什么又要弄出来右值这个东西来烧脑呢? 原因还是在于对于压榨出高性能的需求,就象Linux 系统命令 cpmv, 原先的值拷贝好比 cp, 现在的右值用于移动语义好比 mv

什么是右值,一句话,有名字的是左值,没名字的右值,就因为右值没有名字,它们都是一个临时的变量,对于它们的复制可以简化为移动,反正临时的无名变量没人会用到。

例子代码

  • 头文件
    run_example.h
#ifndef RUN_EXAMPLE_H_
#define RUN_EXAMPLE_H_#include <stdio.h>
#include <stdint.h>#include <string>
#include <map>
#include <iostream>
#include <memory>#include <unordered_map>
#include <boost/log/trivial.hpp>
#include <boost/program_options.hpp>
#include <boost/core/noncopyable.hpp>
#include <boost/assert.hpp>//old function pointer
typedef int (*exam_func_ptr)(int argc, char** argv);
//new function object
typedef std::function<int(int, char**)> exam_func_t;template<typename T, typename... Ts>
std::unique_ptr<T> my_make_unique(Ts&&... params) {return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
}class Command
{
public:Command();Command(std::string name);Command(const Command& other);Command& operator=(const Command& other);Command(Command&& other);Command& operator=(Command&& other);virutal ~Command();void setName(const std::string& name);void setParameter(const std::string& name, const std::string& value);void setData(const uint8_t* pData, size_t length);friend std::ostream& operator<<(std::ostream&, const Command& obj);private:std::string m_name = "";std::map<std::string, std::string> m_parameters;size_t m_length = 0;uint8_t* m_data = nullptr;
};class ExampleRunner: boost::noncopyable {
public:ExampleRunner();//no need by noncopyable//ExampleRunner(const ExampleRunner& rhs);//ExampleRunner& operator=(const ExampleRunner& rhs);virtual ~ExampleRunner();void init();size_t size() const;void register_example(const std::string& name, const exam_func_t &exam);int execute_example(const std::string& name, int argc, char** argv) const;
private:volatile uint32_t m_example_count = 0;std::unordered_map<std::string, exam_func_t> m_func_examples;
};#endif
  • 实现文件
    run_example.cpp
#include "run_example.h"using namespace std;
namespace po = boost::program_options;extern int function_demo(int argc, char** argv);
extern int lambda_demo(int argc, char* argv[]);
extern int rvalue_demo(int argc, char* argv[]);
extern int smart_ptr_demo(int argc, char** argv);const int CASE_COUNT =4;const char* usage = R"name(please specify example name:function_demoor lambda_demoor rvalue_demoor smart_ptr_demo
)name";//C++11: delegate constructor
Command::Command():Command("") {BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< ". construct: " << m_name << "@" <<this;
}Command::Command(string name):m_name(name) {BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< ". construct: " << m_name << "@" <<this;
}Command::Command(const Command& other) {BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< ". copy construct: " << m_name << "@" <<this;m_name = other.m_name;for (const auto& kv : other.m_parameters) {BOOST_LOG_TRIVIAL(trace) << kv.first << " has value " << kv.second;m_parameters.insert(kv);}std::copy(other.m_data, other.m_data + m_length, m_data);
}Command& Command::operator=(const Command& other) {BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< ". operator =: " << other.m_name;if (this != &other){this->m_name = other.m_name;for (const auto& kv : other.m_parameters) {std::cout << kv.first << " has value " << kv.second << std::endl;m_parameters.insert(kv);}// Free the existing resource.if(m_data) {delete[] m_data;}m_length = other.m_length;m_data = new uint8_t[m_length];std::copy(other.m_data, other.m_data + m_length, m_data);}return *this;
}Command::Command(Command&& other) {BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< " move copy construct: " << other.m_name << "@" <<this;m_name = std::move(other.m_name);m_parameters = std::move(other.m_parameters);// Copy the data pointer and its length from the source object.m_data = other.m_data;m_length = other.m_length;// Release the data pointer from the source object so that// the destructor does not free the memory multiple times.other.m_data = nullptr;other.m_length = 0;}Command& Command::operator=(Command&& other)
{BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< " move operator ==" << other.m_name;if (this != &other){m_name = std::move(other.m_name);m_parameters = std::move(other.m_parameters);// Free the existing resource.delete[] m_data;// Copy the data pointer and its length from the// source object.m_data = other.m_data;m_length = other.m_length;// Release the data pointer from the source object so that// the destructor does not free the memory multiple times.other.m_data = nullptr;other.m_length = 0;}return *this;
}Command::~Command() {BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< ". destruct: " << m_name ;
}void Command::setName(const string& name) {m_name = name;
}
void Command::setParameter(const string& name, const string& value) {m_parameters[name] = value;
}void Command::setData(const uint8_t* pData, size_t length) {BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__<< ". setData: " << m_name;if(nullptr != m_data) {delete[] m_data;}m_length = length;m_data = new uint8_t[length];std::copy(pData, pData + length, m_data);
}ostream& operator<<(ostream& os, const Command& obj)
{os << obj.m_name;os << ": ";//for (map<string, string>::iterator it = obj.m_parameters.begin(); it != obj.m_parameters.end(); ++it)for (const auto& kv : obj.m_parameters){os << kv.first << "=" << kv.second << endl;}for(size_t i=0; i< obj.m_length; ++i) {os << *(obj.m_data + i);}return os;
}ExampleRunner::ExampleRunner(): m_example_count(0),m_func_examples() {BOOST_LOG_TRIVIAL(trace)<<"* ExampleRunner construct: " ;
}ExampleRunner::~ExampleRunner() {BOOST_LOG_TRIVIAL(trace)<<"* ExampleRunner destruct: ";
}void ExampleRunner::init() {register_example("function_demo", function_demo);register_example("smart_ptr_demo", smart_ptr_demo);register_example("lambda_demo", lambda_demo);register_example("rvalue_demo", rvalue_demo);
}void ExampleRunner::register_example(const string& name, const exam_func_t &exam)
{m_example_count++;m_func_examples[name] = exam;
}int ExampleRunner::execute_example(const string& name, int argc, char** argv) const
{auto it = m_func_examples.find(name);if(it != m_func_examples.end()) {BOOST_LOG_TRIVIAL(trace) << "execute "<< it->first;exam_func_t func = it->second;return func(argc, argv);}BOOST_LOG_TRIVIAL(trace) << "not registered "<< name;return -1;
}size_t ExampleRunner::size() const {return m_func_examples.size();
}int main(int argc, char** argv)
{unique_ptr<ExampleRunner> runner = my_make_unique<ExampleRunner>();runner->init();BOOST_ASSERT_MSG(runner->size()==CASE_COUNT, "example count should be 2");//c++11 R"raw string"po::options_description desc("Allowed options:");desc.add_options()("help,h", "produce help message")("name,n", po::value<string>(), usage);po::variables_map vm;po::store(po::parse_command_line(argc, argv, desc), vm);po::notify(vm);    if (vm.count("help")) {BOOST_LOG_TRIVIAL(trace) << desc << "\n";return 1;}if (vm.count("name")) {BOOST_LOG_TRIVIAL(trace) << "* example name is "<< vm["name"].as<string>() << ".";runner->execute_example(vm["name"].as<string>(), argc, argv);} else {BOOST_LOG_TRIVIAL(trace) << "example name was not set.";BOOST_LOG_TRIVIAL(trace) << desc ;}return 0;
}

关于智能指针和移动拷贝的例子

  • boost_memory.cpp
#include "run_example.h"using namespace std;int rvalue_demo(int argc, char* argv[])
{//move constructorCommand cmd1(Command("c1"));//copy constructorCommand cmd2 = cmd1;shared_ptr<Command> sharedPtr = make_shared<Command>("update");sharedPtr->setParameter("user", "alice");uint8_t nBytes[3]   = { 0x00,0x01,0x02 };sharedPtr->setData(nBytes, 3);shared_ptr<Command> sharedPtr2 = sharedPtr;BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__ << ". sharedPtr=" << sharedPtr.get() << ", "<< sharedPtr.use_count() <<", command="<< *sharedPtr;BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__ << ". sharedPtr2=" << sharedPtr2.get() << ", "<< sharedPtr2.use_count() <<", command="<< *sharedPtr2;return 0;
}int smart_ptr_demo(int argc, char* argv[])
{BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__ << " -- unique_ptr --";//unique_ptr<Command> ptr = unique_ptr<Command>(new Command());unique_ptr<Command> uniquePtr = my_make_unique<Command>();uniquePtr->setName("create");uniquePtr->setParameter("user", "walter");BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__ << ". unique pointer=" << uniquePtr.get() <<", command="<< *uniquePtr;BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__ << ". -- shared_ptr --";shared_ptr<Command> sharedPtr = make_shared<Command>();sharedPtr->setName("retrieve");sharedPtr->setParameter("user", "walter");BOOST_LOG_TRIVIAL(trace) << "line " <<__LINE__ << ". shared pointer=" << sharedPtr.get() << ", "<< sharedPtr.use_count() <<", command="<< *sharedPtr;return 0;
}

运行结果

./bin/run_example -n rvalue_demo
[2020-10-07 13:59:40.303527] [0x0000000107d9edc0] [trace]   * ExampleRunner construct:
[2020-10-07 13:59:40.304168] [0x0000000107d9edc0] [trace]   * example name is rvalue_demo.
[2020-10-07 13:59:40.304179] [0x0000000107d9edc0] [trace]   execute rvalue_demo
[2020-10-07 13:59:40.304198] [0x0000000107d9edc0] [trace]   line 27. construct: c1@0x7ffeed644df0
[2020-10-07 13:59:40.304204] [0x0000000107d9edc0] [trace]   line 61 move copy construct: c1@0x7ffeed644db0
[2020-10-07 13:59:40.304210] [0x0000000107d9edc0] [trace]   line 100. destruct:
[2020-10-07 13:59:40.304234] [0x0000000107d9edc0] [trace]   line 31. copy construct: @0x7ffeed644df0
[2020-10-07 13:59:40.304255] [0x0000000107d9edc0] [trace]   line 27. construct: update@0x7faa5c407408
[2020-10-07 13:59:40.304264] [0x0000000107d9edc0] [trace]   line 112. setData: update
[2020-10-07 13:59:40.304281] [0x0000000107d9edc0] [trace]   line 19. sharedPtr=0x7faa5c407408, 2, command=update: user=alice[2020-10-07 13:59:40.304289] [0x0000000107d9edc0] [trace]   line 20. sharedPtr2=0x7faa5c407408, 2, command=update: user=alice[2020-10-07 13:59:40.304295] [0x0000000107d9edc0] [trace]   line 100. destruct: update
[2020-10-07 13:59:40.304315] [0x0000000107d9edc0] [trace]   line 100. destruct: c1
[2020-10-07 13:59:40.304319] [0x0000000107d9edc0] [trace]   line 100. destruct: c1
[2020-10-07 13:59:40.304327] [0x0000000107d9edc0] [trace]   * ExampleRunner destruct:

参考资料

  • https://www.modernescpp.com/index.php/what-is-modern-c
  • https://github.com/lefticus/cppbestpractices
  • https://github.com/isocpp/CppCoreGuidelines

http://www.taodudu.cc/news/show-6465526.html

相关文章:

  • 用java有理数类包含加减乘除,7.1 面向对象的简介 - VimL 语言编程指北路
  • 2.6_4 Reids数据类型 + 基础命令
  • 分数四则运算java_用java具体代码实现分数(即有理数)四则运算
  • matlab显示格式,Matlab基础学习-----数据显示格式(设置)
  • C++ : Boost : Rational 有理数类
  • MATLAB学习第二天(基础语法、变量、命令以及新建自己文件)
  • matlab命令整理-1
  • 学习笔记 Matlab 命令 -4
  • 4.MATLAB常用命令
  • linux中l没有ll命令,manjaro linux没有ll等命令的解决办法
  • 应用逻辑:haskell生成有理数集合
  • 分类梨和苹果的两种方法
  • c语言孔融分梨函数代码,孔融分梨
  • PTA-孔融分梨(函数实现)
  • 小孩儿吃梨问题c语言,C语言编程练习 6.2课上编程练习.docx
  • PTA 7-207 孔融分梨(函数实现)
  • 7-207 孔融分梨(函数实现)
  • 入门级动态规划-分梨
  • 动态规划(分梨、最长公共子序列)
  • 练习题 G: 分梨
  • 中国大学MOOC第六周作业孔融分梨
  • dp专题:分梨
  • 分梨(简单递归)
  • 7-207 孔融分梨(函数实现)7-208 sdut-C语言实验- 数列求和2
  • 孔融分梨c语言
  • c语言函数孔融分梨,ACM题目:孔融分梨
  • c语言编码孔融分梨,孔融分梨的故事
  • 【递归问题】分梨
  • 孔融分梨1
  • 题解:分梨----递归,动态规划

现代C++改变了什么相关推荐

  1. 点击改变div高度_css实现div两列布局(两种方法)

    一.应用场景 左侧一个导航栏宽度固定,右侧内容根据用户浏览器窗口宽度进行自适应 二.思路 首先把这个问题分步解决,需要攻克以下两点: 1.让两个div并排到一行 2.让一个div宽度固定,另个div占 ...

  2. 解决LC_ALL: 无法改变区域选项 (UTF-8): 没有那个文件或目录的问题

    问题: -bash: 警告:setlocale: LC_ALL: 无法改变区域选项 (UTF-8): 没有那个文件或目录 -bash: 警告:setlocale: LC_ALL: 无法改变区域选项 ( ...

  3. Qt中如何改变三角形图形项的包围盒

    Bounding Rect 和 Shape 的联系与区别 Bounding Rect 将 item 的外边界定义为矩形,所有绘制必须限制在此区域内,QGraphicsView 使用它来确定 item ...

  4. 改变自己,让自己变得更好

    在现实生活中,有些时候我们会想着去改变别人,希望别人能顺从自己一点,这样心里会好受一些:但往往让我们想不到的是,每个人都有自己的想法,都有自己的主见: 并不是每个人都能理解你,都会按你的意愿去顺从你的 ...

  5. 人要懂得放下已经发生,却又无法改变的事情

    在生活中,有些事情如果注定是无法改变的,那么就尽可能快的释怀,要坦然接受,坚强的走出来.毕竟很多事情,不会因为你的悲伤,结果就会改变. 不如,果断看开放下,然后收拾心情重新开展好的事情发展.未来的路还 ...

  6. 在批评中改变自己,才能真正取得进步

    在工作中难免会遇到上司批评时候,而批评一般有两种:有一种批评是带有情绪的批评,这种批评往往来自于你的上司,因为你工作上的问题激怒了你的上司. 当你面对这样的批评时要微笑,然后倾听,这个时候千万不要辩解 ...

  7. view(*args)改变张量的大小和形状_pytorch reshape numpy

    20201227 这个方法是在不改变数据内容的情况下,改变一个数组的格式,参数及返回值,官网介绍: a:数组–需要处理的数据 newshape:新的格式–整数或整数数组,如(2,3)表示2行3列,新的 ...

  8. Android ListView 点击item改变item的背景颜色(ListView实现光标移动)

    一下demo 地址 实现的效果图如下 ListView 光标移动,实现很是简单,这里是指item背景的改变 使用 listSelector listSelector  用户指定当前选中item 的颜色 ...

  9. Ubuntu 系统禁止或者改变中文简体切换繁体,方便使用AS全局搜索

    使用Ubuntu 系统 开发的我们在使用android studio 或者idea 在使用全局搜索的时候发现确实切换中文简体字和繁体字 很烦闹,自己也不使用繁体字就把切换禁止了算了 下面说下禁止的方法 ...

  10. js 点击改变内容与vue 点击改变内容

    js 的代码如下 <!DOCTYPE html> <html><head><meta charset="UTF-8"><tit ...

最新文章

  1. 年终总结,程序员票选最喜欢的编程语言花落谁家?
  2. js、jquery实用小技巧集合
  3. Bootstrap的轮播图
  4. Linux 命令之 curl -- 文件传输工具/下载工具/网络接口调试
  5. 【POJ - 3310】Caterpillar(并查集判树+树的直径求树脊椎(bfs记录路径)+dfs判支链)
  6. webpack打包原理
  7. 在Hadoop集群实施成功后再次格式化名称节点,datanode无法加入集群的处理办法
  8. 农艺师需要职称计算机,评农艺师需要发表几篇论文?
  9. Java native方法String转char*以及String[]转char**
  10. 《大型数据库技术》MySQL管理维护
  11. docker制作python项目镜像
  12. 有关液压的相关知识(1)-螺纹与齿轮泵
  13. AI学习路线和书籍分享
  14. 分享PHP多功能在线工具箱网站源码,安装教程详解
  15. Latex学习之插入编号-实心圆点列表,横杆,数字
  16. SNAT、DNAT、MASQUERADE的区别
  17. java课程设计 计算器_Java课程设计-计算器
  18. winimage使用教程
  19. python给excel排序_用python处理excel数据(六)实现excel表中排序功能
  20. 基于javaweb+jsp的鲜花花卉销售管理系统(JavaWeb MySQL JSP Bootstrap Servlet SSM SpringBoot)

热门文章

  1. 如何从详情页获取淘宝/天猫商品的分类?
  2. linux nvidia 361.run,Ubuntu 16.04+Nvidia GTX 1080+CUDA8.0 深度学习环境配置
  3. 宣传部第二学期第一次培训
  4. 22071班(11月29日)
  5. B2B电子商务策略[在2022年发展您的业务]
  6. DLNA DMR实现
  7. oracle scn超了,Oracle安全 - SCN的可能最大值与耗尽问题
  8. 【驱动代码移植高通平台之二十三】高通平台i2c设备驱动
  9. 未来计算机发展趋势作文,未来的计算机作文300字(精选3篇)
  10. Opportunity