Back to the Basics! Essentials of Modern C++ Style
来源:互联网 发布:济南公交线路查询软件 编辑:程序博客网 时间:2024/04/28 04:34
Herb Sutter @ CppCon2014, video can be found here.
Default == don’t overthink. Esp. don’t optimize prematurely.
- Write for clarity and correctness first.
- Avoid premature optimization. By default, prefer clear over optimal.
- Avoid premature pessimization. Prefer faster when equally clear.
Raw Pointers vs Smart Pointers
- Express ownership using
unique_ptr
wherever possible, including when you don’t know whether the object will actually ever be shared. That is, writemake_unqiue
by default ormake_shared
when needed. - Don’t use Owning
*
,new
ordelete
any more, except rarely inside the implementation details of low-level data structures. - Do use Non-Owning
*
and&
, especially for parameters. Prefer passing objects by*
or by&
as usual, just like always. - When deferencing a global (static or heap) or aliased local refcounted pointers e.g.
shared_ptr<widget> g_p
, take its unaliased + local copy at the top of a call treeauto pin = g_p
otherwiseg_p
might disappear. - Don’t copy/assign refcounted smarted pointers, including pass-by-value or in loops, unless you really want the semantics they express: altering object lifetime. In that case, refer to the following code.
unique_ptr<widget> factory(); // source - produces widgetvoid sink(unique_ptr<widget>); // sink - consumes widgetvoid reseat(unique_ptr<widget>&); // "will" or "might" reseat ptrvoid thinke(const unique_ptr<widget>&); // usually not what you wantshared_ptr<widget> factory();// source + shared ownershipvoid share(shared_ptr<widget>); // share - "will" retain refcountvoid reseat(shared_ptr<widget>&); // "will" or "might" reseat ptrvoid may_share(const shared_ptr<widget>&); // "might" retain refcount
Use auto
whenever possible
Prefer declaring local variables using auto
, whether the type should be track or stick. This guarantees zero implicit coversions/temporaries, zero narrowing conversions and zero uninitialized variables.
- Deduced and exact, when you want tracking:
auto x = init;
Q: Does this “=” create a temporary objects plus a move/copy?
A: Standard says “No”. The codeT x = a;
has exactly the same meaning asT x(a);
when a has typeT
(or derived fromT
)… andauto x = a;
guarantees the types are the same, so it always means exactly the same as autox(a)
. - Write explicit typename, when you want to commit:
auto x = Type{init};
Q: Does this “=” create a temporary objects plus a move/copy?
A: Standard says “Yes, but”: the compiler elide the temporary. In practice compilers do (and in the future routinely will) elide this
temporary+move. However, the type must still be movable (which
includes copyable as a fallback).
The C++ world is moving to left-to-right: Auto variables, standard-defined literals, User-defined literals, Function declarations (tailing return type or just auto
since C++14, Named lambdas, Aliases with using
(no more typedef
), Template aliases. As to auto variables, here is another example where auto
is better:
base* pb = new derived();unique_ptr<base> pb = make_unique<derived>(); // too subtle: people keep not seeing itauto pb = unique_ptr<base>{make_unique<derived>()}; // explicit and clear: hard to miss it
There are cases where you can’t use “auto
style”: type{}
with non-(cheaply-)movable type.
auto lock = lock_guard<mutex>{m}; // error, not movableauto ai = atomic<int>{}; // error, not movableauto a = array<int, 50>{}; // compiles, but needlessly expensive
Return-by-value vs Pass-by-value
Use return-by-value way more often, but don’t overuse pass-by-value.
Just as exception safety isn’t all about writing try
and catch
, using move semantics isn’t all about writing move
and &&
.
Howard Hinnant: “Don’t blindly assume that the cost of construction is the same as assignment.”
For strings and vectors, capacity plays a large role in their performance. Copy construction always allocates (except for short). Copy assignment (except for short) allocates/deallocates 50% of the time with random capacities on the lhs and rhs. To keep an eye on performance, one must count allocations and deallocations.
Constructors are the primary case of multiple “in + retain copy” (pass-by-value) parameters, where overloading const&/&& is combinatorial.
Uses and Abuses of Forwarding Reference
The name of &&
is expected to be changed from universal reference to forwarding reference in the new print of Scott Meyer’s “Effective Modern C++”.
- Use
&&
only for parameter/return types. (1)myclass&&
rvalue references to optimize rvalues, usually overloadingconst& /&&
.
(2)T&&
forwarding references to write forwarders, which are neutral code between unknown callers and callees and want to preserve rvalueness/cv-ness. - Don’t use auto&& for local variables. You should know whether your variable is const/volatile or not except rarely if you’re just handing it off in the body of a forwarder
- Back to the Basics! Essentials of Modern C++ Style
- Welcome Back to C++ (Modern C++)
- Quiz: The basics of C
- The Essentials of Filters
- Essentials of the JMX
- The Essentials of Filters
- Back to Basics: Using KVO
- Elements of Modern C++ Style
- Elements of Modern C++ Style
- Lack of money back to the moon
- The basics of Silvermoon
- The basics of swift
- The Basics of Numpy
- The Basics of the MMAPI for Java Developers -> Introduction to the MMAPI
- The Prisoner of Zenda——8、Back to Zenda
- Basics of the Unix Philosophy
- Chapter6 The Basics of JavaScript
- The Basics Of Image Filtering
- hdu 2045 不容易系列之(3)—— LELE的RPG难题(java)
- 多进程解码网络编程模型选择的漫谈
- 绑定变量让sql重新硬解析的方法及11g自适应游标
- MySQL5.6.11安装步骤(Windows7 64位)
- Oracle学习(九)之删除日志组和日志文件
- Back to the Basics! Essentials of Modern C++ Style
- Using Machine Learning to Name Malware
- 跟上节奏 大数据时代十大必备IT技能
- opendns安全研究成果
- 复合对象的构造和析构顺序
- Hashtable、HashMap和TreeMap的区别
- 并行计算圆周率
- android 布局padding的使用
- Modbus通讯协议学习 - 认识篇