【问题标题】:Why does the return type of a friend function that is overloading the "<<" operator have to be a reference?为什么重载“<<”运算符的友元函数的返回类型必须是引用?
【发布时间】:2015-06-24 16:50:41
【问题描述】:
friend ostream &operator<<( ostream&, Complex& );

为什么我不能直接使用

friend ostream operator<<( ostream&, Complex&);

【问题讨论】:

    标签: class c++11 overloading pass-by-reference friend


    【解决方案1】:

    按值返回意味着对象需要被复制,否则它可能无效,这对于流可能会带来问题,因为原始(复制的源)对象可能会在调用其析构函数时自行清理。通过引用返回可以避免这种情况,更重要的是,链式调用将共享相同的ostream,而不是在每个&lt;&lt; 调用之后共享一个新流。

    【讨论】:

      【解决方案2】:

      这不是一个严格的要求。如果你使用非参考版本,

      ostream << a << b << c
      

      将在操作符

      【讨论】:

        【解决方案3】:

        std::ostream 明确阻止您复制它。请注意,它有一个已删除的复制构造函数。

        因此,如果你试图按值返回它,会导致编译器错误。

        【讨论】:

          【解决方案4】:

          不是必须,但有几个原因可以解释为什么这是一个常见的选择。

          许多处理流的 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
          }
          

          Live Example

          如果要按值返回,这不可能在一行中完成

          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
          }
          

          Live Example

          在后者中,通过引用返回的常见情况几乎是必须的。

          除了这些情况之外,没有人强迫您通过引用返回。它还取决于您的用例,更重要的是,取决于您的对象如何管理其资源(请记住,如果不涉及 RVO,则按值返回可能涉及析构函数)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-07-20
            • 1970-01-01
            • 2023-03-07
            • 2011-03-07
            相关资源
            最近更新 更多