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

這個網誌中的熱門文章

大彎國家公園: 四日行程 Four Days in Marfa & Big Bend