const 方法使用引用修改对象
const method modifies object using reference
下面的代码调用一个const
方法,该方法传递对成员的引用,然后修改该成员。
#include <iostream>
struct A {
int i;
A(int _x) : i(_x) { }
void calc(int& j, const int value) const { j = value; }
void set1() { calc(i, 1); }
};
int main()
{
A a(3);
std::cout << a.i << std::endl;
a.set1();
std::cout << a.i << std::endl;
return 0;
}
代码使用 gcc 6.4.0 和 clang 5.0.2 编译,没有警告。
代码合法吗? 从non-const
方法调用时,const
方法calc
能够修改对象。
成员函数上的const
限定符适用于*this
实例。
在calc()
中,this
是指向常量A
的指针,但是参数j
是由非常量引用获取的,所以这是完全标准的行为。
现在,如果您在calc
中尝试分配给this->i
,则代码将无法编译。
void A::calc(const int value) const
{
i = value; // Compilation error here: i is a data member of a const instance
}
同样,如果set1
成为 const 成员函数,则代码将不会编译(因为它会尝试将this->i
绑定到非 const 引用获取的参数(
当然。标记方法const
只是*this
const
,即函数承诺不会通过写入this
来修改对象。
仍然可以通过其他方式修改对象(假设它们也没有标记为const
,例如示例中的int& j
(。
请记住,拥有像const Thing*
这样的"const 指针"或像const Thing&
这样的"const 引用"并不意味着在拥有指针/引用时不能更改 const 限定的对象。 这仅意味着您不能使用该特定指针/引用作为更改它的一种方式。但是可能还有其他名称、指针或引用允许更改它。
举几个例子:
void f1(const int& arg1, int& arg2) {
std::cout << "arg1 before: " << arg1 << "n";
arg2 = 4;
std::cout << "arg1 after: " << arg1 << "n"; // same thing?
}
f1
看起来好像它必须始终在"之前"和"之后"行中打印相同的值。 但如果有人将相同的int
反对传递给两个参数,则不会:
void call_f1() {
int n = 7;
f1(n, n); // Prints before 7, after 4!
}
或者,如果函数调用介于 const 引用的两种使用之间,则类似地可以以某种方式更改变量:
void something_else();
void f2(const int& arg) {
std::cout << "arg before: " << arg << "n";
something_else();
std::cout << "arg after: " << arg << "n";
}
int n = 2;
void something_else() { n = 8; }
void call_f2() {
f2(n); // Prints before 2, after 8!
}
因此,在您的void A::calc(int& j, const int value) const
函数中,this
指针确实是const A* const
,这意味着您无法使用this
指针更改A
对象。 但是仍然可以有其他方法可以更改它,例如在这里您有一个对非常量对象的int& j
引用。 如果碰巧j
引用了*this
的子对象,则修改j
是修改*this
子对象的有效方法。 这类似于我上面的f1
示例,其中arg1
不能用于更改引用的int
,但arg2
可以,如果它们引用相同的int
,这意味着arg1
已更改。
当首先使用const
限定符定义变量时,情况略有不同。 如果我们写
const A a(3);
然后我们确实得到了一个保证(除了在构造函数和析构函数期间(,对象不能以任何方式更改。 该语言通常会阻止您意外尝试,例如a.set1()
,但即使您尝试const_cast
技巧,任何实际更改都将是未定义的行为。
你的代码没有错。声明方法const
仅意味着this
是常量。但是,您的方法不会(直接(修改this
或this
的任何成员。 考虑这个人为的,尽管是正确的例子:
struct foo {
int value;
void modify_const(foo& f) const { f.value = 5; }
};
int main() {
foo f;
f.value = 3;
f.modify_const(f);
}
该方法不会修改this
,并且参数被声明为非常量,因此在const f
上调用f.modify_const(f);
将失败,因为参数被传递为非常量。
只是表明你永远不会安全。const
限定符并不能保证值永远不会更改。
尝试这样,你可以做一些非常讨厌的事情:
#include <iostream>
class A {
const int i;
void calc(int& j, const int value) const { j = value; }
public:
A(int _x) : i(_x) { }
void set1() const { calc(*const_cast<int*>(&i), 1); }
int getI() const { return i; }
};
int main()
{
const A a(3);
std::cout << a.getI() << std::endl;
a.set1();
std::cout << a.getI() << std::endl;
return 0;
}
- QML:修改在不同QML文件(而非main.QML)中定义的子对象的属性
- 为什么不能修改对象中的值?另外,我如何改进此链表?
- 使用可变允许修改unordered_set中的对象
- 未定义的对象(〔basic.life〕/8):为什么允许引用重新绑定(和常量修改)
- 如何修改函数中的对象?
- 通过引用在矢量中放置和修改对象
- 为什么我可以通过原始指针而不是shared_ptr来修改对象
- const 方法使用引用修改对象
- 在C 向量中修改对象值的麻烦
- 修改对象也会修改同一类的所有其他对象
- SFML-无法在窗口中修改对象
- 如何使用 *& 修改对象 C++
- 修改对象与修改该对象的副本
- 指针指向矢量调用的方法无法修改对象
- 带函子修改对象的Const函数
- 如何在构造函数中初始化的函数中修改对象大小的2D向量
- 从复制构造函数外部修改对象成员时导致向量内存损坏,但从复制构造函数内部修改时不会
- 如何在不调用成员函数的情况下修改对象
- visualstudio 2012-如何在c++中修改对象已知内存地址
- 在集合内修改对象的可变成员是否安全