从C++看编程语言发展脉络

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,5000CU*H 3个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 【5月更文挑战第1天】自1979年以来C++历经40年发展,以其复杂语法影响了Go、Rust和Zig等语言。 回顾C++11,引入了范围for循环、Lambda表达式、自动类型推导、统一初始化、删除和默认函数、nullptr、委托构造器、右值引用、新标准库如线程支持及算法等。C++持续演进,保持其在编程语言中的影响力。

1 简介

C++自1979年首次实现带有类的C以来,已经存在了40年。

现在其C++ 的语法已经非常复杂。

其发展路径具有重要的参考意义,特别是像go,rust这样的类似的语言。

Rust从C++中学到了内存安全的重要性,Zig从C中选择了更细分的内存分配,Go则带上“指针”和“垃圾收集”两件法宝自成一派。

而其C++26已经在规划之中...
也就是 2026年将要发布的版本。

对于C++26,将努力在该标准中具有以下内容:

    * 执行
    * 代码范围
    * 反射

在没有特定场景的情况下,将优化

  • 合约

    Contracts 类似 assert 和 static_assert 的语法,可以在函数声明时使用。

  • 模式匹配

经常说C++需要像它这样的新控制语句头上需要一孔,图案匹配显示很多希望 提供比我们所能提供的更好的 过滤器/链/选择 近似于纯图书馆设施。

模式匹配 通过以下方式提高类型安全性 使编写类型安全代码比编写 传统的 C 型或传统的C++式替代品更好。
此外,它还将访问者置于 在许多情况下,模式。
这不仅仅是另一个控件结构;它与类型系统交互。

在这个领域有相当多的工作正在进行中,在 C++26 时间范围内给它播出时间。

如何运送,以及 以什么形式,目前还不完全清楚。

做为一个经典版本,C++ 11 出现了大量新特征,几乎成为一个新语言。

这里主要回顾C++11的新的特征。包括新的算法,新的容器类原子操作,类型特征,正则表达式,新的智能指针,async()功能多线程库。

 C++11 延迟,
 C++14 准时,
 C++17 准时 ,
 C++20 准时, 
 C++23 将准时,
 C++26 将按时

而C++曾经也是一位昂扬向上的少年,现在只不过是经历了40年之久青年。

1 c++11更新

1.0,基于范围的for循环

int nArr[5] = {1,2,3,4,5};
for(int &x:nArr){
    x *=2; //数组每个元素倍乘
}

1.1,Lambda表达式

允许定义本地功能, 消除大部分乏味而且有安全风险的函数对象。

[capture](parameters)->return-type{body}

[]指示lambda表达式的开始

int main()
{
    char s [] = "hi";
    int Uppercase = 0;
    for_each(s, s+sizeof(s), [&Uppercase] (char c)){
        if (isupper(c))
          Uppercase++;
    });
   cout<< Uppercase<<"uppercase letters in:" << s<<end1;
}

类似与定义一个函数,将其主主体放置在另一个函数调用。[&Uppercase] &表示lambda主体获得对Uppercase的引用,如果没有&,

大写字母将按值传递,C++11 lambda也包括用于成员函数的构造。

1.2,自动类型推导 decltype, Automatic Type Deduction

编译器自动推断i为int类型

    auto i = 1; 

在v11 之前C++ 在声音对象时 必须指定对象类型,很多情况下,对象的声明包括初始化程序, C++11充分利用了这一点,可用在不指定对象类型的情况下声明对象。

auto x=0; //x has type int because 0 is int
auto c='a'; //char
auto d=0.5; //double
auto national_debt=14400000000000LL;//long long

auto不再指定具有自动存储类型的对象。相反,它声明一个对象,该对象的类型可从其初始值设定项推导, 声明一个迭代器

auto ci=vi.begin();

标准模板库容器的判断

  vector<int> vec(6,10);
  vector<int>::iterator iter=vec.iterator();
  auto iterAuto = vec.iterator(); //相比较更方便

1.3,统一初始化语法

C++ 11 使用统一的大括号表示初始化

    std::string s("hello");
    int m=int(); //默认初始化 default initialization

在某些情况下,可用将 = 用于相同目的

    std::string s="hello";
    int x=5;

对于POD聚合,使用花括号

int arr [4] = {0,1,2,3};
today struct tm = {0};

最后构造函数使用成员初始化程序

structs {
    int x;
    s():x(0) {}};
}

1.4,删除函数 和 默认函数

默认函数

struct A {
    A()=default; // C++11 only 指示编译器生成该函数的默认实现
    public: C();
};

默认函数有两个优点:它们比手动实现更有效,并且使程序员摆脱了手动定义这些函数的麻烦。

删除函数

int func()=delete;

已删除的函数对于防止对象复制很有用

    =delete:

    struct NoCopy
    {

     NoCopy & operator =( const NoCopy & ) = delete;

     NoCopy ( const NoCopy & ) = delete;

    };

    NoCopy a;

复制出错

    NoCopy b(a); //compilation error, copy ctor is deleted

1.5,nullptr

一个关键字,它指定空指针常量。

nullptr替换了NULL多年来容易被用作空指针替代的易于出错的宏和立即数0(macro and the literal)。nullptr是强类型的

void f(int); //#1
void f(char *);//#2
//C++03
f(0); //which f is called?
//C++11
f(nullptr) //unambiguous, calls #2

nullptr 适用于所有指针类别,包括函数指针和成员指针

const char *pc=str.c_str(); //data pointers
if (pc!=nullptr)
  cout<<pc<<endl;
int (A::*pmf)()=nullptr; //pointer to member function
void (*pmf)()=nullptr; //pointer to function

1.6,委托建造者 Delegating Constructors

C++11 中构造函数可调用同一类的另一个构造函数

    class M //C++11 delegating constructors
    {int x, y;
     char *p;
     public:
     M(int v) : x(v), y(0), p(new char [MAX]) {} //#1 target
     M(): M(0) {cout<<"delegating ctor"<<endl;} //#2 delegating };

委托构造器#2调用目标构造器#1

1.7, 右值参考

C ++ 03中的引用类型只能绑定到左值。C ++ 11引入了新的引用类型类别,称为rvalue引用。

右值引用可以绑定到右值,例如临时对象和文字

    void naiveswap(string &a, string & b)
    {string temp = a;
     a=b;
     b=temp; }

以上例子需要分配内存,使用右值引用可不分配内存,效率更高

void naiveswap(string &a, string & b)
{

伪代码

 size_t sz = empty.size();
 const char * p = empty.data();

将填充的资源移为空

 empty.setsize(filled.size());
 empty.setdata(filled.data());

填充为空

 fill.setsize(sz);
 fill.setdata(p);
}

1.8,新增标准库

TR1标准包括新的容器类

unordered_set, onordered_map,onordered_multiset, nordered_multimap

正则表达式,元组,功能对象包装,文档库

1.8.1,线程库 并发

promise 和 futures 线程类,在并发环境中用于同步的对象
用于启动并发任务的async()
声明线程tread_local存储类型

1.8.2 新的算法

可模仿集合理论运算的新算法 all_of()

none_of()
ispositive() 范围[first,first+n]

并使用all_of(), any_of()

#include <algorithm>

C ++ 11代码,所有元素都是积极的吗?

all_of(first,first + n,ispositive()); //假

至少有一个积极因素?

any_of(first,first + n,ispositive()); //真

这些元素都不是积极的吗?

none_of(first,first + n,ispositive()); //假

复制数组copy_n()

    #include
    int source [5] = {0,12,34,50,80};
    int target[5];
    // copy 5 elements from source to target
    copy_n(source, 5, target);

iota()创建一系列按顺序递增的值,就像通过将初始值分配给*first

然后使用 ++ 前缀递增该值。 下例中 iota()将连续值{10,11,12,13,14}分配给数组arr,并将{'a', 'b' 'c'} 分配给 char数组

include <numeric>
int a[5]={0};
char c[3]={0};
iota(a, a+5, 10); //changes a to {10,11,12,13,14}
iota(c, c+3, 'a'); //{'a','b','c'}

1.9, 后置返回类型 tailng-return-type

template Ret adding_func(const Lhs &lhs, Const Rhs &rhs){return lhs + rhs;}

C++11的合法语法,添加后置返回类型

template auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}

更普遍的函数声明和定义

struct SomeStruct {
    auto func_name(int x, int y) -> int;
};
auto SomeStruct::func_name(int x, int y) -> {
    return x + y;
}

1.10, 显示重写 override final

struct Base{
    virtual void some_func(float);
};
struct Derived:Base{
    virtual void somt_func(int) override; // 错误,不会重写基类方法
};

override 编译器将检查基类中有没有一个具有相同签名的虚函数
final用于防止基类被继承和防止子类重写

    struct Base1 final { };
struct Derived1 : Base1 { }; // 病态的, 因为类Base1被标记为final了
struct Base2 {
    virtual void f() final;
};
struct Derived2 : Base2 {
    void f(); // 病态的, 因为虚函数Base2::f 被标记为final了.
};
  • 最大整型

    long long int

1.11, 允许sizeof运算符可用在类型数据成员使用,无需明确对象

struct p {otherClass member;};
sizeof(p:member);

1.12, 元组 tuple

由预先确定数量的多种对象组成,元组可用看作时struct数据成员泛化。

使用可变参数模板,元组的定义时这样的

template <class ...Types> class tuple;

下面是定义和使用元组的一个例子:

typedef std::tuple <int, double, long &, const char *> test_tuple;
long lengthy = 12;
test_tuple proof (18, 6.5, lengthy, "Ciao!");
lengthy = std::get<0>(proof);  // 把'lengthy' 赋值为18.
std::get<3>(proof) = " Beautiful!";  // 修改元组的第四个元素

1.13,常量constexpr

保证函数或者对象构造函数在编译器常量

constexpr int GetFive() {return 5;}
int some_value[GetFive() + 7];

產生12個整數的陣列。合法的C++11寫法

2 小结

自2011年C++标准的重大修正以来,2020年的C++20被称为又一个里程碑。 而C++26也在计划之中。

C++一般被人认为是C的超集,但是这并不完全准确。

相比C语言,C++早期的新功能就包括

类,成员函数,派生类,单独的编译,
公共和私有访问控制,友元,函数参数的类型检查,默认参数,内联函数,重载运算符,
构造函数,析构函数,调用和返回函数,并发库,虚函数,复数,
引用,命名空间,异常处理,模板,容器,IO流等。

C++20更引入了检查程序实体,例如检查变量,枚举,类及其成员,lambda及其捕获功能等。

大部分C语言代码可以很轻易地在C++正确编译,但是仍有少数差异,导致某些有效C代码在C++失效。

如果需要混用它们,则需要在C++中调用,必须放在 extern "C"{/C代码/}内。

参考

https://en.wikipedia.org/wiki/C++11

https://www.open-std.org/
目录
相关文章
|
6月前
|
存储 算法 搜索推荐
在C++编程语言中数组的作用类型
在C++编程语言中数组的作用类型
61 0
在C++编程语言中数组的作用类型
|
6月前
|
算法 程序员 编译器
C++与C语言的差异:编程语言之间的奥秘探索
C++与C语言的差异:编程语言之间的奥秘探索
98 0
|
6月前
|
存储 程序员 C++
在C++编程语言中指针的作用类型
在C++编程语言中指针的作用类型
69 0
|
6月前
|
机器学习/深度学习 开发框架 人工智能
探索C++的深邃世界:编程语言的魅力与实践
探索C++的深邃世界:编程语言的魅力与实践
|
Java 程序员 Apache
编程语言比拼之Java VS C++
Java和C++都是非常受欢迎的编程语言,各有各的优势和适用场景。以下是对它们的简要比较:
148 0
|
3月前
|
算法 C# 开发工具
《黑神话:悟空》背后的编程语言揭秘——超越C++的多元技术融合
【8月更文挑战第27天】在游戏开发领域,一款游戏的成功往往离不开其背后强大的技术支持和编程语言的精妙运用。《黑神话:悟空》作为备受瞩目的国产单机动作游戏,其开发过程不仅涉及了多种编程语言,更是一次技术创新的集中展现。然而,当我们深入探讨其开发语言时,会发现它并非仅依赖于单一的C++,而是融合了多种编程语言的优势,共同铸就了这款游戏的辉煌。
254 0
|
5月前
|
算法 Java 程序员
【C++】挑战与机遇并存的编程语言—前序
【C++】挑战与机遇并存的编程语言—前序
48 1
|
5月前
|
Java Go C#
编程语言C#、C++、Java、Python、go 选择哪个好?
我想说的是,不论选择哪种编程语言,决定选择的都是你最终的目的,做选择之前,先充分调研每一个选择项,再做选择思路就会非常清晰了。
120 3
|
5月前
|
C++
C++ 是一种面向对象的编程语言,它支持对象、类、继承、多态等面向对象的特性
C++ 是一种面向对象的编程语言,它支持对象、类、继承、多态等面向对象的特性
|
6月前
|
编解码 JavaScript 前端开发
【专栏】介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例
【4月更文挑战第29天】本文介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例。Base64编码将24位二进制数据转换为32位可打印字符,用“=”作填充。文中展示了各语言的编码解码代码,帮助开发者理解并应用于实际项目。
147 1