Address
:
[go:
up one dir
,
main page
]
Include Form
Remove Scripts
Accept Cookies
Show Images
Show Referer
Rotate13
Base64
Strip Meta
Strip Title
Session Cookies
More Web Proxy on the site http://driver.im/
Submit Search
よいコード、わるいコード
•
64 likes
•
22,394 views
京大 マイコンクラブ
Follow
KMCの例会講座で発表された、C++でよいコードを書くための指南。
Read less
Read more
1 of 28
Download now
Downloaded 46 times
More Related Content
よいコード、わるいコード
1.
よいコード、わるいコード 京都大学理学部数学系4回生 KMC ID: hatsusato 2015/05/11
2.
2/28 自己紹介 ● hatsusato – 理学部数学系4回生 ● 最近は数学基礎論とか集合論とかやってる。 ● プログラミング言語を作りたい。 –
趣味 ● 作画アニメ – すきなもの ● C++ – きらいなもの ● C++
3.
3/28 よいコード わるいコード ● そんなの ひとの
かって – ではない。 – 良いコード、悪いコードは存在する。
4.
4/28 よいコード わるいコード ● この講座では、良いコード、悪いコードの例(当社調べ) を挙げることで啓蒙しようと思います。 –
サンプルコードには、良いコードを書くのが難しいと定評 のある[要出典]、C++を用います。 ● 僕がC++と言ったらそれはC++11以降のC++のことです。 – 他の言語ではあまり役に立たないアドバイスもあるか も。 ● 良いコード、悪いコードを知って、ライバルに差を つけろ!
5.
5/28 よいコード わるいコード ● ここでの良いコードとは、保守性の高いコードの ことを指すものとします。 – 機能の追加・修正を行い易く、バグが発生しにくい。
6.
6/28 目次 ● 一貫性 – 初期化 – オブジェクトの整合 ● 疎結合 –
間接メンバアクセス – 非メンバ関数 – const教 ● 例外安全 – No new, No delete
7.
7/28 一貫性 ● コードの一貫性を保つ – 何をしたいコードなのかを誰が読んでもわかるようにす る。 – コードの表記の一貫性を保つ ● コーディング規約とか。 –
オブジェクト表現の一貫性を保つ ● オブジェクトのコード上の見た目と表現する実体とを一致させ る。
8.
8/28 初期化 ● まず初期化しろ – 未初期化オブジェクトはしばしば未定義動作を引き起こ し、デバッグを困難にする。
9.
9/28 初期化 ● まだパフォーマンスを気にするような時間じゃな い – 初期化をあとですることによるパフォーマンス向上<< <<越えられない壁<<<<デバッグの利便性 – パフォーマンスは、ベンチマークを取ってから検討する。 –
プログラムの処理にかかる時間の80%は、コード全体の 20%の部分が占める。
10.
10/28 オブジェクトの整合 ● 悪い例 – Cでは文字列を格納する領域を表現するのに、先頭ポイ ンタと領域の長さとの2つで表現する。 – 2つは密接に関連するのに、別々に管理される。 整合性のないオブジェクトが簡単に出来てしまう! #include
<cstdio> char* fgets(char* str, int count, FILE* stream);
11.
11/28 オブジェクトの整合 ● 良い例 – stringクラスは文字列の情報をまとめて管理する。 オブジェクトの整合性は常に保たれる! #include <string> istream&
getline(istream& input,string& str);
12.
12/28 オブジェクトの整合 ● お互いに強く依存するオブジェクトはまとめて管 理する。 – 我々が通常構造体などを導入して行っていること。 ● 単にまとめるだけでなく、オブジェクト全体が常に有 効な状態になるようにする。 – stringの保持する文字数とsize()とは連動する。
13.
13/28 疎結合 ● 各コンポーネント間の依存度をできるだけ下げる – 問題を細かく分割して考えることができる。 – 変更のもたらす影響の範囲を把握しやすくなる。 –
コンポーネントの再利用性が高まる。
14.
14/28 間接メンバアクセス ● 悪い例 – オブジェクトのメンバに直接アクセスしている。 メンバの名前との依存関係がオブジェクトの外にま で染み出してしまう! #include <utility> pair<int,
int> pii; pii.first = 0; pii.second = 1;
15.
15/28 間接メンバアクセス ● 良い例 – オブジェクトのメンバに間接的にアクセスしている。 メンバへのアクセスが抽象化され、自由度が増加! #include <tuple> tuple<int,
int> tii; get<0>(tii) = 0; get<1>(tii) = 1;
16.
16/28 間接メンバアクセス ● メンバ変数より関数の方が疎結合 – 関数でアクセスするようにしておけば、変数の名前や表 現方法を変更しても、ユーザコードに影響しないように できる。
17.
17/28 非メンバ関数 ● 悪い例 begin()やend()をメンバとしてもたないオブジェクト に対して適用できない! template <typename C,
typename F> void foreach(C&& c, F&& f) { for (auto it = c.begin(); it != c.end(); ++it) { f(*it); } }
18.
18/28 非メンバ関数 ● 良い例 begin()やend()のオーバーロードを追加すること で、任意のオブジェクトに対して拡張できる! template <typename C,
typename F> void foreach(C&& c, F&& f) { for (auto it = begin(c); it != end(c); ++it) { f(*it); } }
19.
19/28 非メンバ関数 ● メンバ関数より非メンバ関数の方が疎結合 – メンバ関数は対応するクラスとの依存関係がある。 – メンバ関数はthisポインタへのアクセス権を持つので、ク ラスメンバとの依存性も高い。
20.
20/28 const教 ● 悪い例 sを書き換えるつもりがないのに書き換わっている! int s[5] =
{0, 1, 2, 3, 4}; int d[5] = {}; for (int i = 0; i < 5; ++i) { s[i] = d[i]; }
21.
21/28 const教 ● 良い例 constをつければオブジェクトの不変性を明示でき る! const int s[5]
= {0, 1, 2, 3, 4}; int d[5] = {}; for (int i = 0; i < 5; ++i) { s[i] = d[i]; // compile error }
22.
22/28 const教 ● const教 is
何? – ローカル変数を含めたあらゆるオブジェクト・関数にでき るだけconst修飾を施す思想のこと。 – constを付けずに書けるところでも、できるだけconstを 使って書くようにする。 – const教らしいコードの例 ● constをつければ実際安心! const int n = [](){ int tmp = 0; cin >> tmp; return tmp; }();
23.
23/28 例外安全 ● C++は例外機構を持つ – 例外が発生すると、従来のC的なエラーハンドリングで は対処できない不整合が発生しうる。 –
例外が発生した時に、リソースリークやデータの不整合 が発生しない保証を例外安全という。 ● 例外安全は難しい – 難しいからと言って諦めては、良いコードは書けない。 ● 例外安全でないコードはその時点で潜在的なバグを持つ。 – 例外安全を意識する姿勢は大切。
24.
24/28 No new, No
delete ● 悪い例 secondの確保に失敗した場合、firstがリークする! struct X { X() : first(new int(1)), second(new int(2)) {} ~X() { delete first; delete second; } int *first, *second; };
25.
25/28 No new, No
delete ● 良い例 IntPtrがそれぞれのリソースを管理するのでリーク しない! struct IntPtr { IntPtr(int n) : ptr(new int(n)) {} ~IntPtr() { delete ptr; } int *ptr; }; struct X { X() : first(1), second(2) {} IntPtr first, second; };
26.
26/28 No new, No
delete ● もっと良い例 newやdeleteは自分で書かない! template <typename T, typename... Args> unique_ptr<T> make_unique(Args&&... args) { return unique_ptr<T>( new T(forward<Args>(args)...)); } struct X { X() : first(make_unique<int>(1)), second(make_unique<int>(2)) {} unique_ptr<int> first, second; };
27.
27/28 No new, No
delete ● 訓練されたC++erはdeleteを書かない – newもラップして使うので、直接書かない。 ● デストラクタは1つの仕事だけをする – デストラクタが複数の仕事をしている。 → 対応する複数の初期化が存在する。 → 複数の仕事は同時にはできない。 → 一部しか初期化が済んでない段階で例外が投げら れると不整合が発生する。 → 例外安全でない。
28.
28/28 まとめ ● 変更に耐えるコードを書くよう心がけよう! – キーワード:一貫性・疎結合 – 例外安全は難しいけど、少しずつ慣れていこう。 ● 良いコードは身を助く –
将来困らないように(困らせないように)、今のうちに注意 しておこう。
Download