通过复制含义

时间:2014-05-19 23:10:06

标签: c++ g++

好的,我正在考虑以下C ++代码:

foo (std::string str) {
  // do whatever
}

foo(const char *c_str) {
  foo(std::string(c_str));
}

我看一下这段代码并认为它​​需要重写以通过引用传递。基本上,我担心构造函数将被调用两次,一次在const char *版本的foo中,并且当参数作为std :: string传递给foo时再次被调用,因为它被设置为通过副本传递。我的问题是:我是对的,还是g ++足够聪明,可以将构造函数放在c字符串版本中并称之为好?似乎g ++无法做到这一点,但我只是希望真正知道的人可以澄清它。

3 个答案:

答案 0 :(得分:1)

理论上将涉及两个构造函数(一个用于创建临时文件,另外还有用于传递副本的复制构造函数);实际上,显式允许编译器执行复制省略(C ++11§12.8¶32)。

但是你不需要两个重载开始。

正常的方法是只拥有一个const std::string &的函数版本。如果调用者已经有std::string,则不执行任何复制,因为我们通过引用传递。如果它具有char *,则创建临时std::string(因为它具有来自const char*的非显式构造函数)并传递给函数(因为const引用可以绑定到临时工)。

答案 1 :(得分:0)

你可以用惯用的方式写

foo (std::string const& str) {
  // do whatever
}

不需要重载,因为你可以隐式构造一个临时的:

foo("yes");

如果您打算在某处存储参数的值,可以使用右值引用:

foo (std::string && str) {
   my_member = std::move(str);
}

但是为了避免过载爆炸,按值获取参数通常是一个很好的中间点:

无论有关idomatic参数传递的所有这些好的服务,是的,编译器可以在as-if规则下优化掉虚假副本(尽管复制构造函数需要可访问,就好像复制完成)

答案 2 :(得分:0)

由于传递给foo的临时名称未命名,因此直接构造参数,消除副本似乎是一个相当简单的优化,尽管标准不保证这一点(因为没有优化是)。

更一般地说,你应该通过常量引用,除非你的函数已经获取参数本身的副本(例如,可能复制和变异),