C++ 牛逼!
Posted 编程指北
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 牛逼!相关的知识,希望对你有一定的参考价值。
大家好,我是周六的小北。
我们都知道,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++
中找到。
预告:
不要错过更新哟~
以上是关于C++ 牛逼!的主要内容,如果未能解决你的问题,请参考以下文章
此 Canon SDK C++ 代码片段的等效 C# 代码是啥?
我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情