文章目录
前言
C++是一种多范式的语言,已经存在了几十年。自诞生以来,C++发生了很大的变化。当C++11问世时,C++语言的创造者 Bjarme Stroustrup 说,C++11感觉像是一种全新的语言。C++20的发布标志着这头野兽”进化的另一个里程碑,为编写代码的方式带来了类似的革命。然而,这些年来,有
件事是不变的:语言的哲学思想。
- 简而言之,C++的哲学思想可以概括为三条规则:
- C++底层不应该基于任何其他语言(汇编语言除外)。
- 只为使用的东西付费(不需要为没有使用到的语言特性付费)。
- 以低成本提供高级抽象(更高的目标是零成本提供高级抽象)。
不为没有使用的东西付费意味着,如果想在栈(stack)上创建数据成员,那么就可以这么做。许多语言会在堆(heap)上分配对象,但这对于C++来说不是必要的。在堆上分配对象会有一些代价–可能分配器必须为此锁定互斥锁,这在某些类型的应用程序中可能是个很大的负担。这么做的好处是,可以轻松地分配变量,而无须每次动态分配内存。高级抽象是C++与C或汇编语言等低级语言的区别。高级抽象允许直接在源代码中表达思想和意图,这非常有利于保证语言的类型安全性。
请考虑以下代码片段:
struct Duration
{
int _millis;
};
void example()
{
auto d = Duration{};
d._millis = 100;
auto timeout = 1; //second
d._millis = timeout;//ouch,we meant 1000 millis but assigned just 1
}
更好的做法是利用语言提供的类型安全特性:
#include <chrono>
using namespace std::literals::chrono_literals;
struct Duration
{
std::chrono::milliseconds _millis;
};
void example()
{
auto d = Duration{};
//d._millis = 100; compilation error, as 100 could mean anything
d._millis = 100ms;//okay
auto timeout = 1s;//or std::chrono::seconds(1);
d._millis =
timeout;//okay,converted automatically to milliseconds
}
上述现象可以使我们免于犯错误,并且这样做时不会付出任何代价。它生成的汇编代与第一个示侧的相同。这就是为什么它被称为零成本抽象。有时,在C++中使用抽象实上会比不使用抽象产生更好的代码。这种语言特性的一个例子是C++20的协程(coroutine)由标准库提供的另一组优秀的抽象集是算法。以下哪段代码更容易阅读,也更容易证明没有 bug?哪个能更好地表达编程想法?
//Approach #1
int count_dots(const char *str, std::size_t len)
{
int count =0;for(std::size_ti=0;i<len; ++i)
{
if(strli]==')
count++;
}
return count;
//Approach #2
int count dots(std::string_view str)
{
return std::count(std::begin(str),std::end(str),'.');
}
第二个需数有一个不同的接口,但即使保持接口不变,我们也可以从指针和字符串长度std::string_view。因为它是一种轻量级的类型,所以应该由编译器对它进行优化
使用更高级的抽象会让代码更简单、更可维护。C++语言从诞生以来就一直在努力提供零成本的抽象,所以我们应该在此基础上构建程序,而不是使用较低层次的抽象来重新设计。