C++についての覺書

C++についての細々した覺書を纏めておくための文書。「C++ Tips その1」といふ由來の古い文書もある。

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)を返す、といふもの。消した筈の要素が(moveした後の「殘骸」ではあれども)[newlast, last)に存在したままになつてゐることに注意せねばならない。

もう少し嚙み碎いて説明しよう。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}となる。

亂數

ツイッターに書いたものの、再び探し出す羽目に陷つたので覺え書きしておく。

#include <random>

// 亂數生成器の定義
std::random_device seedGen;  // 非決定論的亂數生成器。シード生成に利用。
std::mt19937_64 engine(seedGen());  // 64bit版メルセンヌ・ツイスター法による疑似亂數生成器
std::uniform_int_distribution<> dist(1, 6);  // 1〜6の整數を一樣分布で得るためのdistribution

// 亂數の生成
int x = dist(engine);

疑似亂數生成器を用ゐずstd::random_device::operator()をガンガン呼び出すやうなことも出來るみたいだが、コストとかどうなのかねえ。