【发布时间】:2015-06-24 16:50:41
【问题描述】:
friend ostream &operator<<( ostream&, Complex& );
为什么我不能直接使用
friend ostream operator<<( ostream&, Complex&);
【问题讨论】:
标签: class c++11 overloading pass-by-reference friend
friend ostream &operator<<( ostream&, Complex& );
为什么我不能直接使用
friend ostream operator<<( ostream&, Complex&);
【问题讨论】:
标签: class c++11 overloading pass-by-reference friend
按值返回意味着对象需要被复制,否则它可能无效,这对于流可能会带来问题,因为原始(复制的源)对象可能会在调用其析构函数时自行清理。通过引用返回可以避免这种情况,更重要的是,链式调用将共享相同的ostream,而不是在每个<< 调用之后共享一个新流。
【讨论】:
这不是一个严格的要求。如果你使用非参考版本,
ostream << a << b << c
将在操作符
【讨论】:
std::ostream 明确阻止您复制它。请注意,它有一个已删除的复制构造函数。
因此,如果你试图按值返回它,会导致编译器错误。
【讨论】:
不是必须,但有几个原因可以解释为什么这是一个常见的选择。
许多处理流的 STL 类和对象通常选择按引用返回,因为这允许 链接
class MyClass {
public:
MyClass(int v) : value(v) {}
int value;
friend MyClass &operator<<( MyClass&, MyClass& );
};
MyClass &operator<< (MyClass& a, MyClass& b) {
a.value += b.value;
return a;
}
int main() {
MyClass a(2);
MyClass b(3);
MyClass c(5);
a << b << c; // Chaining
std::cout << a.value; // 10
}
如果要按值返回,这不可能在一行中完成
a << b; // Can't chain
a << c;
关于上述类的另一个重要原因是,处理流意味着您不能复制流 (https://stackoverflow.com/a/6010930/1938163),因为它不太有意义。
这也意味着如果你将流对象保持在对象的状态中,你就不能按值返回(你会得到一个隐式删除的复制构造函数)
class MyClass {
public:
MyClass(std::string str) {
ss << str;
}
std::stringstream ss; // This CANNOT be copied
friend MyClass operator<<( MyClass&, MyClass& );
};
MyClass operator<< (MyClass& a, MyClass& b) {
a.ss << b.ss.str();
return a; // Can't do this! Copy ctor is implicitly deleted due to ss
}
在后者中,通过引用返回的常见情况几乎是必须的。
除了这些情况之外,没有人强迫您通过引用返回。它还取决于您的用例,更重要的是,取决于您的对象如何管理其资源(请记住,如果不涉及 RVO,则按值返回可能涉及析构函数)。
【讨论】: