C++ Tips その1
C++を使つてゐる上でTipsとして書き留めておかうと思つた小さなこと。
文字列の入力
- 執筆: 平成20年4月2日
1行づつ文字列を入力していく例として、web上のあちこちで下の樣なコードを見かける。
#define BUFSIZE 256
std::string allString;
while (cin.good()) {
char buf[BUFSIZE];
std::cin.getline(buf, BUFSIZE - 1);
allString += buf;
allString += "\n";
}
暴言を吐かせて貰ふと、これぢや、折角C++のstringを使つてゐるのが臺無しである。1行が想定文字數越えてゐたらどうするの? それよりなにより、Cの亡靈が取り憑いてゐるやうなコードで、個人的には、想定文字數の前提が崩れないとしても、格好惡いコードだと思ふ。
std::getline(std::istream&, std::string&);といふ函數が標準で用意されてゐる。『プログラミング言語C++ 第3版』でも取り上げられてゐるものである。これを利用すると、1行の長さの前提を氣にせずに濟むし、格好良くなる。(と、支配人は思ふ。)
上のコードを、書き直してみると、下の樣になる。
std::string allString;
while (cin.good()) {
std::string line;
std::getline(std::cin, line);
allString += line;
allString += "\n";
}
string の += を使ふより、ostringstreamに吐かせた方が效率的であるとか、色々改良の餘地はあるかも知れない。それでも、上のコードよりは良いんぢやないかと思ふのだが、いかがであらうか。
參考
- B. Stroustrup, “プログラミング言語C++ 第3版,” p. 685, 長尾高弘 譯, Addison Wesley Publishers Japan, 1998.
インスタンスのコピーの禁止のさせ方の今昔
- 執筆: 平成20年4月24日
インスタンスのコピーを禁止したいクラスをつくりたいとき、といふのはあるもので、昔から有名なTipsとして存在してゐた。コピーコンストラクタと、代入演算子 (operator =) をprivateで宣言して、中身を實裝しない、といふものである。まあ、下のやうな感じ。
class NonCopyableA
{
// ...
private:
NonCopyableA(const NonCopyable &); // 宣言だけする
NonCopyableA& operator=(const NonCopyable &); // 宣言だけする
// ...
};
これで、NonCopyableAについては、コピーも代入も出來ないやうになつてめでたしめでたし、となつてゐた訣である。更には、NonCopyableAを繼承したクラスも、少なくともそのままだとコピー出來ない代物になる。
この、あまりによく知られたTipsを、使ひ廻すといふアイデアは、筆者も持つてゐて、さういふクラスをつくつて使ひ廻してゐたが、Boostにきちんと用意されてゐることを最近知つた。まあ、そりやさうやわな。皆が獨自に書いても害はなささうであるが、時間が勿體ない。
boost::noncopyableといふのが用意されてゐるので、これをprivate繼承したらいい。まあ、この例は確かにis-a關係とは言ひ難いものな。下のやうな感じ。
#include <boost/utility> // for boost::noncopyable
class Hogehoge : boost::noncopyable
{
// ...
};
int main()
{
Hogehoge h1, h2;
h1 = h2; // 代入出來ないのでこれはアウト
Hogehoge h3(h1); // コピー出來ないのでこれもアウト
// ...
}
氣分的には、かなり樂になつたやうに感じる。ただ、中身がブラックボックス化された訣なので、C++を學習してゐる人には、コピーコンストラクタと代入演算子をprivateで宣言して放置といふ遣り方を、一度は自分で書いて欲しいとは思ふけれどね。
boost::bind()
- 取り敢へず執筆: 平成21年11月19日
書くと書いてから全然書いてなかつたが、思ひ出した (つふか、書いてあるのを見つけた) ので、書いておく。
函數を引數として渡すときに、一部の引數に固定値を與へたい場合というのが、時にある。さういふ時に使へるアダプタがboost::bind()。
クラスのメンバ函數を渡すときに、特定のインスタンスと結び附けることも出來るので、なんとも強力
boost::bind(fnc, arg1, arg2, arg3, ...)のやうな感じで函數fncと、引數argNを渡してやれば、アダプタが返つてくるので、それを渡してやればいい。渡された側でfncに突つ込む引數を指定するには、argNに_1、_2などと指定すればいい。
メンバ函數とインスタンスを結び附けるには、boost::bind(fnc, obj, ...)などとすればいい。
サンプルコードは、そのうち用意します。


