C++ Tips その1

C++を使つてゐる上でTipsとして書き留めておかうと思つた小さなこと。



文字列の入力

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に吐かせた方が效率的であるとか、色々改良の餘地はあるかも知れない。それでも、上のコードよりは良いんぢやないかと思ふのだが、いかがであらうか。

參考


インスタンスのコピーの禁止のさせ方の今昔

インスタンスのコピーを禁止したいクラスをつくりたいとき、といふのはあるもので、昔から有名な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()

書くと書いてから全然書いてなかつたが、思ひ出した (つふか、書いてあるのを見つけた) ので、書いておく。

函數を引數として渡すときに、一部の引數に固定値を與へたい場合というのが、時にある。さういふ時に使へるアダプタがboost::bind()。

クラスのメンバ函數を渡すときに、特定のインスタンスと結び附けることも出來るので、なんとも強力

boost::bind(fnc, arg1, arg2, arg3, ...)のやうな感じで函數fncと、引數argNを渡してやれば、アダプタが返つてくるので、それを渡してやればいい。渡された側でfncに突つ込む引數を指定するには、argNに_1、_2などと指定すればいい。

メンバ函數とインスタンスを結び附けるには、boost::bind(fnc, obj, ...)などとすればいい。

サンプルコードは、そのうち用意します。




© 2008-2009 oZ/acy. ALL RIGHTS RESERVED.