C++についての覺書

C++についての細々した覺書を纏めておくための文書。

unique_ptr<>

auto_ptr<>は非推奬。代りにunique_ptr<>を使ふべし。

無論、必要な場合にはshared_ptr<>などを使ふ。

「例外仕樣」非推奬化

MSYSを導入し(その手順はこちら)、ClangでC++17に追從しよう、とか思つてゐたら、早速ぶち當たつたのが、「error: ISO C++17 does not allow dynamic exception specifications」といふ宣告。どういふことかについては「非推奨だった古い例外仕様を削除」に詳しい。

左邊値、右邊値の話

ムーヴだのなんだのを扱ふ際には把握しておかなければ困るのだが、細かいところがなかなか把握できないものの一つ。

調べ物をしてゐるときに割と良い感じの説明を見附けたので、備忘としてリンクを張つておく。

std::remove(あるいはstd::remove_if)の羂

<algorithm>に入つてゐるstd::remove(first, last, v)あるいはstd::remove_if(first, last, pred)の擧動は、[first, last)のうちの殘すべき要素をfirstから順に間を開けず順序が保存されて竝ぶやうにmoveし、殘すべき最後の要素の次を指すイテレータ(newlast)を返す、といふもの。[newlast, last)に要素が(moveした後の「殘骸」ではあれども)存在したままになつてゐることに注意せねばならない。

もう少し嚙み碎いて説明しよう。std::vector<int> vecA = {1, 5, 2, 4, 5, 3};なるvecAがあつたとする。こいつから5を削除しようとしてstd::remove(vecA.begin(), vecA.end(), 5);としたとき、vecAの中身は{1, 2, 4, 3}とはならない。{1, 2, 4, 3, X, Y}のやうになり、3の次(つまりXの位置)を指すイテレータを返す。vecA.size()の返す値に變化はない。

故に、要らないものを完全に消し去るには、newlast = std::remove(vecA.begin(), vecA.end(), 5);としておいた上で、vecA.erase(newlast, vecA.end());のやうにする必要がある。

R3.5.1追記

C++20では、STLのコンテナに對しては、std::erase(container, v) や std::erase_if(container, pred) が追加されたので、それらに任せてしまふ方が樂になると思しい。(vector, list, deque, forward_listに對しては両者ともに、set/map系に對しては後者のみが追加された。)

上のvecAの例であれば、std::erase(vecA, 5);とやれば、vecAの中身が{1, 2, 4, 3}となる。