以下代码块出现在Scott Meyers的着名书籍"Effective C++"第3项:
中class TextBlock {
public:
...
const char& operator[](std::size_t position) const
{
... // do bounds checking
... // log access data
... // verify data integrity
return text[position];
}
char& operator[](std::size_t position)
{
... // do bounds checking
... // log access data
... // verify data integrity
return text[position];
}
...
private:
std::string text;
};
作者指出,在上面的实现中,const
和非const
重载的内容基本相同。为了避免代码重复,它可以简化为:
class TextBlock {
public:
...
const char& operator[](std::size_t position) const // the same as before
{
...
...
...
return text[position];
}
char& operator[](std::size_t position) // now just calls const op[]
{
return // cast away const on
const_cast<char&>( // op[]'s return type;
static_cast<const TextBlock&>(*this) // add const to *this's type;
[position] // call const version of op[]
);
}
...
private:
std::string text;
};
我的问题是:
我们何时需要const T&
的重载和T&&
的重载? (这里,T
可能是模板参数或类类型,因此T&&
可能是也可能不是通用引用。我可以看到,在标准库中,许多类都提供了重载。例子是std::pair
和std::tuple
的构造函数,有大量的重载。 (好的,我知道在这些函数中,其中一个是复制构造函数,其中一个是移动构造函数。)
是否有类似的技巧来分享const T&
和T&&
重载的实现?我的意思是,如果const T&&
重载返回一个复制构造的对象,并且T&&
重载返回一些移动构造的东西,在共享实现之后,该属性仍然必须保持。 (就像上面的技巧一样:const
返回const
而非 - const
返回非const
,无论是在实现共享之前还是之后)
谢谢!
我指的两个重载应该是这样的:
Gadget f(Widget const& w);
Gadget f(Widget&& w);
与rvalue引用返回无关,即:
Widget&& g(/* ... */);
(顺便说一下,这个问题在my previous post)
中得到了解决在上面的f()
中,如果Gadget
是可复制构造和可移动构造的,那么除了阅读实现之外没有办法告诉返回值是复制构造还是移动 - 建造。没有什么可以处理返回值优化(RVO)/命名返回值优化(NRVO)。 (见my previous post)
答案 0 :(得分:2)
•我们什么时候需要为const T&amp; amp;另一个用于T&amp;&amp;?
基本上,当移动为你带来性能提升时,应该还有一个移动构造函数。这同样适用于您需要昂贵副本的功能。
在您的示例中,如果您返回对char
的引用,则建议不要设置返回右值引用的函数。相反,按价值返回并依赖编译器应用RVO的能力(参见例如here)
•是否有类似的技巧来分享const T&amp; amp;的实现?和T&amp;&amp;重载?
我经常发现使用通用引用(我懒惰)设置构造函数或函数很有用,例如
struct MyClass
{
template<typename T /*, here possibly use SFINAE to allow only for certain types */>
MyClass(T&& _t) : t(std::forward<T>(_t)) {}
private:
SomeType t;
};
编辑:关于您的更新:如果您的函数Widget
中有f
的昂贵副本,则建议过载{{1} }}
Widget&&
你可以使用像这样的函数模板组合这两个函数
Gadget f(Widget const& w)
{
Widget temp = w; //expensive copy
}
Gadget f(Widget&& w)
{
Widget temp = std::move(w); //move
}
......我没有说它更好; - )。
编辑2 :另请参阅this thread,它可以更加充分地解决您的问题。