【问题标题】:write to a const reference of ostream写入 ostream 的 const 引用
【发布时间】:2014-11-10 17:48:07
【问题描述】:

我正在阅读 C++ 入门。我遇到了以下代码:

#include <iostream>
#include <string>

using namespace std;

class PrintString {
public:
    PrintString(ostream &o = cout, char c = ' '): os(o), sep(c) {}
    void operator() (const string &s) const { os << s << sep; }
private:
    ostream &os;
    char sep;
};


int main() {
    const PrintString printer;

    printer("ABC");

    return 0;
}

这段代码有效,但我不知道为什么。以下是我的想法,如果有人能帮助指出我错在哪里,那就太好了......

这里,'printer' 是一个 const PrintString 对象,所以它的数据成员是 const,所以 'printer.os' 是对 cout 的 const 引用。因此,我们应该无法写入“printer.os”,因为写入 cout 会改变它。

提前致谢!

【问题讨论】:

    标签: c++ reference constants cout


    【解决方案1】:

    reference 没有被修改,只是它所引用的内容。这与指针相同。如果你有一个指向int 数据成员(int*)的指针,在const 成员函数中使用它会使其类型为int* const。您无法更改指针本身,但可以更改它指向的内容。例如:

    struct Foo
    {
        int a;
        int* p = &a;
    
        void foo() const
        {
            p = new int; // ERROR! Not allowed to modify const pointer
            *p = 100; // OK, it's a pointer to a non-const int
        }
    };
    

    所以当使用os 时,您只是在修改它所引用的对象,而不是引用本身。

    【讨论】:

      【解决方案2】:

      您对const-ness 的困惑最好用指针而不是引用来解释。

      假设你有:

      struct A {int data;};
      
      struct B
      {
         B(A* ptr) : aPtr(ptr) {}
         A* aPtr;
      };    
      
      int main()
      {
         A a1;
         A a2;
         const B b(&a1);
         // This makes b a const object.
         // This makes b.aPtr a const pointer. That means, you cannot change where it points to
         // but you can still change the value of what it points to.
         b.aPtr = &a2; // Not ok.
         b.aPtr->data = 10; // OK.    
      }
      

      b.aPtr 的 const-ness 类似于使用原始指针时所看到的。

      int main()
      {
         A a1;
         A a2;
         A* const aPtr1 = &a1;
         // This makes aPtr1 a const pointer. That means, you cannot change where it points to
         // but you can still change the value of what it points to.
         aPtr1 = &a2; // Not ok.
         aPtr1->data = 10; // OK.
      
         A const* aPtr2 = &a1;
         // This makes aPtr2 a pointer to a const object. That means, you can change where it points to
         // but you cannot change the value of what it points to.
         aPtr2 = &a2; // ok.
         aPtr2->data = 10; // Not ok.
      }
      

      在引用方面,它是相似的,但略有不同。没有非const 引用之类的东西。一个引用,一旦被初始化,就不能引用另一个对象。

      A a1;
      A& ref = a1;  // ref cannot be changed to reference any other object.
      

      在你的情况下,

      const PrintString printer;
      

      对成员变量PrintString::osconst-ness 没有影响。它继续引用非const ostream。这允许您使用:

      const PrintString printer;
      printer("ABC");
      

      【讨论】:

        【解决方案3】:

        尝试将引用成员视为 const 指针成员变量,以及当您声明此类的 const 对象时,constness 将如何传播到成员变量。得到 const 的是指针本身,而不是它指向的东西。引用也有相同的语义,问题是引用已经是 const (就像一个 const 指针变量),所以它不会改变它们。

        #include <iostream>
        
        struct S {
            int *p;
            int *const cp;
            int &ref;
        };
        
        int main() {
            using namespace std;
        
            int i = 10;
            const S s{&i, &i, i};
        
            // s.p = &i; // can't do this, s.p gets const
        
            *s.p = 20;  // changing the pointee
            cout << i << endl;
        
            // s.p = &i; // can't do this, s.p was const already, and would get if it weren't
        
            *s.cp = 30;  // changing the pointee
            cout << i << endl;
        
            // s.ref ?; // can't make a reference refer to other object
        
            s.ref = 40;  // changing the pointee
            cout << i << endl;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-13
          • 2011-03-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多