Collection of interesting C++ tricks (Updating)
Advices
Use List Initialization {}
RAII: Resource Acquisition Is Initialization (Safe ways to handle resources)
Top 10 dumb mistakes to avoid with C++ 11 smart pointers
ODR (One Definition Rule)
工作時遇到一個很奇怪的bug:
// A.h
#define SOMETHING 38
// B.h
#define SOMETHING 22
// shared.h
namespace shared {
inline void some_function()
{
const var = {SOMETHING};
std::cout << var;
}
}
// A.cpp
#include "A.h"
#include "shared.h"
some_function();
// B.cpp
#include "B.h"
#include "shared.h"
some_function();
原本預期在A上執行會印出38,B上執行會印出22,結果在B上執行卻跑出38! 詢問同事後,才知道這是個明顯的ODR violation。
我們都知道在header裡面實作function會觸發compiler error,把function inline化則可以去除該error。究竟這背後發生了什麼事? 其實,那個compiler error是警告你違反one definition rule,可能會出現奇怪的錯誤。程式設計師則用inline告訴compiler我知道我在幹嘛,別擔心ODR violation。但夜路走多了總會遇到鬼,linker在某些情況下確實會撞到ODR violation:
- If the variable is in namespace scope
- If in a named namespace or global scope: linker picks one compilation. It’s called “ODR violation” aka “one definition rule violation” if all compiled copies aren’t equivalent.
- If in anonymous namespace, each .CPP file will get its own copy: safe.
- If the variable is in a function
- If in an inline function in non-anonymous namespace: linker picks one. Same ODR violation issue
- If in a static function or enclosed in anonymous namespace: safe.
因此,使用shared header + macros時要格外小心。
Compilation
forward declaration
C++11
rvalue reference
Very Good explanation on Perfect Forwarding!
Get the underlying C array from std::vector
Preferred to use static_cast and dynamic_cast
Boost
Intrusive Container
我們平常用的STL大多為非侵入式容器,什麼東西都可以裝進去,但也無形間做了不少copy or clone造成記憶體負擔。侵入式容器則相反,他僅僅做了資料結構&指針指到你的個別物件。物件本身不存放於容器中,自然就沒有冗餘copy的問題。這可以說是高效能C++ programming的一大利器。不過其缺點也很明顯: 物件必須修改,裝上一些特別接口才能裝進intrusive container。而記憶體不能無腦丟給STL管,也是程式設計師的一大考驗 XD