我正在阅读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会改变它。
提前致谢!
答案 0 :(得分:4)
引用不会被修改,只会被修改。这与指针的作用相同。如果您有指向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
时,您只需修改其引用的对象,而不是修改引用本身。
答案 1 :(得分:2)
使用指针而不是引用更好地解释了与const
的混淆。
说你有:
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
的常量类似于使用原始指针时的效果。
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;
对成员变量const
的{{1}}没有影响。它继续引用非PrintString::os
const
。这允许您使用:
ostream
答案 2 :(得分:1)
尝试将引用成员视为const指针成员变量,以及在声明此类的const对象时const的传播方式如何传播到成员变量。获得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;
}