ゆとりーなの日記

日記的な事を書いて行くと思はれる

文字列リテラルをstd::stringに渡したときのがっかり感

C++で文字列型といえば定番のstd::stringですが、CAPIなんかだと未だにconst char *を使わなければいけません。それどころか現行C++では、fstream系ではconst char *しか使えません。
この手のAPIをラップする関数を作る時、文字列として受け取る型はconst std::string &にするか、const char *の二択になるわけですが、const std::string &の方が色々扱いやすい分こちらを引数の型として問答無用で採用したいところです。しかし文字列リテラルを渡す時にはわざわざstd::stringに変換されるという無駄が発生してしまいます。しかも中でCAPIに渡すわけですから、折角std::stringに変換したのに内部でc_strを呼び出してconst char *に戻すなど二重の無駄です。
この無駄がどれくらいのものかを適当にコードを書いて調べてみました。

#include <iostream>
#include <string>
#include <fstream>
#include <boost/timer.hpp>

void a_string(const std::string &str) {
  std::ifstream fin(str.c_str());
}

void a_c_char(const char * const str) {
  std::ifstream fin(str);
}

int main() {
  boost::timer timer;
  for (int i = 0; i < 100000; ++i) {
    a_string("文字列リテラル");
  }
  std::cout << timer.elapsed() << std::endl;
  timer.restart();
  for (int i = 0; i < 100000; ++i) {
    a_c_char("文字列リテラル");
  }
  std::cout << timer.elapsed() << std::endl;
  return 0;
}
出力
2.816
2.524

やっぱりstd::string版の方が若干遅いようです。この位なら正直あまり気にしなくてもいいかな感はありますが・・・。