C++のshared_ptrを関数への引数として渡す場合はconst参照で

Monday, January 16th, 2012

Channel9にて公開されているC++ and Beyond 2011の動画にて、Andrei Alexandrescu、Scott Meyers、Herb Sutterの三名が、C++ and Beyond 2011の参加者からの質問に回答している。
その中で4:34からの「On shared_ptr performance and correctness」が興味深い。
質問の主旨としては、shared_ptrを関数やメソッドへ渡す場合、const参照で渡すべきかどうかということらしい。つまり、

void func(std::shared_ptr<std::string> s)
{
  ...
}

int main(int argc, char* argv[])
{
  std::shared_ptr<std::string> s = ...;
  func(s);
}

とするか、const参照にして以下のように渡すか、

void func(const std::shared_ptr<std::string> &s)
{
  ...
}

int main(int argc, char* argv[])
{
  std::shared_ptr<std::string> s = ...;
  func(s);
}

どちらがよいかということである。違いが出てくるのは速度である。const参照で渡さない場合、C/C++は値渡し(pass by value)が基本なので、関数の引数として渡すだけでshared_ptrのコピーが行われ、参照カウンタが+1されてしまう。対して、const参照で渡した場合、当然ながら参照渡し(pass by reference)なので+1されない。
Channel9の動画の中では、const参照で渡しなさいとのことである。

実際に、両方のパターンをQueryPerformanceCounterを使って時間計測してみたが、const参照で渡すケースはさすがに動作が速く、QueryPerformanceCounterでも測れませんでした。
実際のアプリケーションでどれだけの性能差が出るかは微妙ですが、Channel9の動画の質問者の環境では10%未満の差とのことです。
性能が向上するのは確かなので、shared_ptrを渡す際はconst参照で渡すが正しいようです。