C++ 牛逼!

430 阅读3分钟

我们都知道,C++是一门难学易用的语言。 难学在于就连他的创始人 Bjarne Stroustrup 都说自己有时候看不懂这门语言了。

长期玩 C++ 都有一种感觉,那就是总觉得这门语言学不完,不管你的水平多高,一定会有你不知道的黑魔法,关键在于你不知道自己不知道。

C++ 是一门支持多范式编程的语言,提供了四种相辅相成的编程思维模式:

object-based:基于对象

object-oriented: 面向对象

procedural-based: 面向过程

generic paradigm: 泛型编程

你可以用C++ 写出 C 风格的代码,也能写出 Java 似的面向对象代码,更能写出天书版的模板元编程。 每一种范式我认为都是正交的,你可以只掌握 C with class,丝毫不会影响你用 C++ 写出优秀的软件。 很多时候看知乎这种论坛上的大佬谈论 C++ 容易被整自闭,他们喜欢用模板元来炫技,很多新手看起来就会比天书。 比如如何快速判断一个元素是否在一个集合中? 这是我在内网看其它大佬给出的解法,使用了C++ 11 可变参数模板和折叠表达式:

template <typename T>
is(const T& target) {
    return false;
}
template <typename T, typename... Args>
inline bool IsContains(const T& target, const Args&... args) {
    return ((target == args) || ...);
}
// use
IsContains(1, 2,3);  // false
IsContains("a", "a", "b", "c"); // true

但是我们用 std::set 一样能达到相同的目的,只不过在集合元素少的情况下,这种写法看起来会更加的 "C++",也更加炫技。 在 C++ 里,你几乎找不到任何一件简单的事。 比如这段 Java 里最普通的代码:

public class Test {
  public void hello(String name) {
    System.out.println("hello " + name);
  }
}

在 C++ 里,刚看完语法的初学者可能会这样写:

class Test {
  public:
   void hello(std::string name) {
     std::cout << "hello " << name;
   }
}

这样虽然能运行,但是效率和规范上都不是最好的。 为啥呢?

这就涉及到 C++ 参数的传递方式,对于上面这种写法,属于值传递,需要额外的拷贝构造带来的开销。 所以你需要将参数改为引用传递: void hello(std::string & name) 这样就行了吗? NO! 由于hello函数内部不涉及到修改 name变量,所以你需要将引用参数用 const 修饰。 一方面可以显示的告诉调用者函数不会修改 name变量,更重要的是,如果不加 const,下面这种情况将会编译报错: Test test; const std::string name = "小北"; test.hello(name); // 编译报错 // 或是这种 test.hello("小北") // 编译报错

由于参数不是const,所以对于 const 变量作为参数将导致编译不过。 但是这种使用场景本身就是合理的,出现这样的错误,只能说明我们的类设计有问题。 所以你需要给参数加上 const: 这样就完了吗? NO! 因为 hello 方法没有被 const 修饰,所以const的 Test 对象无法调用该方法。如:

const Test test;
test.hello("小北"); // 编译报错

但 hello 方法本身不会改变对象成员变量,const 的对象应该能调用呀,所以你得给 hello 方法加上 const 修饰符:

void hello(std::string &name) const {...}

就这么一个简单的方法,在 C++ 里你需要考虑这么多东西才能够完美的运行起来。

在对象生成构造方面,Java 只需要申明一个构造函数就好了。

但是在 C++ 有拷贝构造、拷贝赋值、移动构造、移动赋、析构函数。 每一个类你都需要去考虑是否能够移动,怎么移动,能否拷贝等等。

又比如指针和引用,在 C 中只有指针,Java 中只有引用,而 C++ 是既有指针又有引用,并且引用还区分左值引用、右值引用哦~

还有指针的引用,引用的指针等等,然后再和顶层 const、底层 const 这些结合起来,简直不要太舒服。 写 C++ 的过程你会体会到对性能和减少 overhead 的极致追求。

C++ 固然很难学,但对于没有编程经验的同学,只要不去深入编程语言里每个晦涩难懂的角落。 把注意力集中到 C++ 中最主流、核心的部分,还是可以在 3 个月内学会 C++ 的。

而对于已经有 C、Java 等语言基础的同学则能更快的掌握 C++。 而C++ 进阶是需要不断在实践中去学习的。

C++ 每一次发布新版本都会被吐槽越来越复杂,但是其实每一个新特性的加入都是为了让 C++ 用起来更简单。 比如 C++11 的 range-for 循环:

for (int& x : v) ++x;

v 可以是任意一种容器,C 风格的循环可能是这样的:

for (int i=0; i < MAX; i++) ++v[i];

但是这样可能会有潜在的越界等错误,而 range-for循环则更加优雅和更具通用性。 对于即将到来的 C++20,又将会是像 C++11 一样,是一个“大版本”。 会有一些全新的特性被引入 C++: Concepts Ranges Modules ... C++ 这么复杂难学还能保持这么高生命力,离不开它广泛的应用场景,比如:

桌面应用(如 Adobe PS、Chrome、Microsoft Office 全家桶等)

大型网站后台(比如微信后台、Google 搜索引擎、搜狗等)

游戏和游戏引擎开发(如 Unity)

编译器(如 LLVM/Clang 、 GCC)解释器( V8 引擎、JVM 等)

视觉和智能引擎(如 OpenCV、TensorFlow)

存储、数据库(如 MySQL 和 MongoDB、Rocksdb等 ) 学好 C++ 还有一个好处就是,你再也不怕学其它语言了,因为很多语言的语法,某种程度上来说都可以在 C++ 中找到。

最后,遇到问题多百度,多找大神问也是很重要的,建议进这个群一起聊,跟前辈一起探讨,也会得到很多帮助。也可以交流学习心得,技术问题,可以获取PDF书籍源码、教程等给大家免费使用 。

f2d082717e3f46168762d845ac802313 - 副本.png

f2d082717e3f46168762d845ac802313.png