关于c ++:我应该按值传递字符串还是将指针传递给它?

Should I pass a string by value or pass a pointer to it?

我有一个像这样的函数

1
2
3
4
5
6
7
8
9
10
int myclass::setVersion(std::string ver)
{
  if (ver.size()>1)
  {
    version.swap(ver)
    return 0;
  }
  else
    return -1;
}

我的问题很简单,以字符串指针的形式传递ver更好还是更好?仅供参考,ver是一个小尺寸的字符串(大约8)。编辑:修改ver无所谓。我只想用ver的内容替换version。edit2:我正在使用Visual Studio 2008。


这取决于您希望代码的行为是什么。

这里建议的大多数答案都会改变您发布的代码的行为,因为它们将修改传入的字符串(或者使代码无法编译,因为它无法修改传入的参数)。

在您发布的示例中,传递给myclass::setVersion()的字符串将不会被修改(参数可能会被修改,但这只是传递给字符串的一个副本;当函数返回时,该副本将被销毁)。

对于这种情况,我建议通过一个const std::string&

1
2
3
4
5
6
7
8
9
10
int myclass::setVersion(std::string const& ver)
{
  if (ver.size()>1)
  {
    version = ver;
    return 0;
  }
  else
    return -1;
}

这样,只有在必要时才能复制。

但是,老实说,除非经常调用函数,否则可能没有什么好担心的。


在C++ 11中,可以添加接受RValk引用的重载:

1
2
int myclass::setVersion(std::string& ver);
int myclass::setVersion(std::string&& ver);

这样,您就可以从rvalues和lvalues进行交换。实际上,您可以执行移动任务,而不是执行swap

1
version = std::move(ver);

这可能比swap更快,这取决于std::string的实现。

用法示例:

1
2
3
4
5
6
string getVersion() { return"version2"; }

string v1 ="version1";
a.setVersion(v1);           // lvalue
a.setVersion(getVersion()); // rvalue
a.setVersion("version3");   // rvalue as well

演示

更新:实际上,为了获得最大的灵活性,您必须同时拥有setVersion的两个变体。但我同意其他人的观点,因为所有这些都是过早的优化,只有在分析显示此时存在瓶颈时才应该使用。


请传递一个引用。

1
int myclass::setVersion(std::string& ver)


您希望将ver的内容存储到版本中。必须复印一份,问题是在哪里。

你可以按照你的建议来做,因为交换很快。但我注意到并不是所有的控制路径都会导致版本字符串被分配一个新值。

因此,我建议如下

1
2
3
4
5
6
7
8
9
10
int myclass::setVersion(const std::string& ver)
{
  if (ver.size()>1)
  {
    version = ver;
    return 0;
  }
  else
    return -1;
}

如果ver的大小为1,这将避免复制,在这种情况下,您不希望将字符串复制到版本中。


每当您修改字符串并希望调用者看到更改时,应该通过引用传递它。