如果一个类的const引用数据成员碰巧在此类范围之外进行更改,那么这种不确定的行为是吗?
作为示例,让我们考虑以下C ++代码:
#include <iostream>
class A {
int x;
public:
A(int x): x(x){}
void change(int y){
x = y;
}
friend std::ostream & operator << (std::ostream & os, const A & a){
os << a.x;
return os;
}
};
class B {
const A & a;
public:
B(const A & a) : a(a) {}
friend std::ostream & operator << (std::ostream & os, const B & b){
os << b.a;
return os;
}
};
int main(){
A a(1);
B b(a);
std::cout << a << std::endl;
std::cout << b << std::endl;
a.change(2);
std::cout << a << std::endl;
std::cout << b << std::endl;
}
我的编译器能够正确执行它,并且调试器指示B :: a的x
已更改。
谢谢您的帮助!
这不是未定义的行为。作为const
成员的B
引用仅表示B
的实例不能通过该引用对其进行更改。但是,因为它是一个引用,所以可能会对其进行某些更改-包括B
的其他成员,它们对const
的相同实例具有自己的非A
引用。
比较成员c
与您现有的B
类的添加,请注意,我们正在B::changeA()
内通过非const
引用成功地对其进行更改,并且在C::change()
中从main()
向下进行了更改) :
#include <iostream>
class A {
int x;
public:
A(int x): x(x){}
void change(int y){
x = y;
}
friend std::ostream & operator << (std::ostream & os, const A & a){
os << a.x;
return os;
}
};
class C
{
A& a;
public:
C(A& a) : a{a} {}
void change(int y) { a.change(y); }
};
class B {
const A & a;
C& c;
public:
B(const A & a, C& c) : a(a), c{c} {}
friend std::ostream & operator << (std::ostream & os, const B & b){
os << b.a;
return os;
}
void changeA(int y) { c.change(y); }
};
int main(){
A a(1);
C c(a);
B b(a,c);
std::cout << a << ' ' << b << '\n';
a.change(2);
std::cout << a << ' ' << b << '\n';
b.changeA(3);
std::cout << a << ' ' << b << '\n';
c.change(4);
std::cout << a << ' ' << b << '\n';
}
查看它在Coliru上实时运行,它打印:
1 1
2 2
3 3
4 4
您不能使用对对象的常量引用来更改对象,但是如果对象不是常量或使用对对象的非常量引用,则可以更改对象本身。
请考虑以下演示程序。
#include <iostream>
int main()
{
int x = 10;
int &rx = x;
const int &crx = x;
std::cout << "rx = " << rx << '\n';
std::cout << "crx = " << crx << '\n';
rx = 20;
std::cout << "rx = " << rx << '\n';
std::cout << "crx = " << crx << '\n';
return 0;
}
其输出为
rx = 10
crx = 10
rx = 20
crx = 20
与使用指向常量数据的指针相同。例如
#include <iostream>
int main()
{
int x = 10;
int *px = &x;
const int *cpx = &x;
std::cout << "*px = " << *px << '\n';
std::cout << "*cpx = " << *cpx << '\n';
*px = 20;
std::cout << "*px = " << *px << '\n';
std::cout << "*cpx = " << *cpx << '\n';
return 0;
}