从c++历程看编程语言的发展

举报
码乐 发表于 2024/04/16 15:21:58 2024/04/16
【摘要】 1 简介C++自1979年首次实现带有类的C以来,已经存在了40年。从了解它的发展历程中去了解语言的发展。现在其C++ 的语法已经非常复杂。其发展路径具有重要的参考意义,特别是像go,rust这样的类似的语言。Rust从C++中学到了内存安全的重要性,Zig从C中选择了更细分的内存分配,Go则带上“指针”和“垃圾收集”两件法宝自成一派。而其C++26已经在规划之中…也就是 2026年将要发...

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/
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。