Ðаn*_*Ðаn 4 c++ member assignment-operator
对于struct有const会员
struct point { const int x; const int y; };
Run Code Online (Sandbox Code Playgroud)
用作会员数据
struct Foo
{
point pt{ 0, 0 };
void move_x(int value);
};
Run Code Online (Sandbox Code Playgroud)
如何Foo::move_x()写更新Foo::pt?可以使用memcpy()吗?
#include <memory.h>
void Foo::move_x(int value)
{
const point pt_{ pt.x + value, pt.y };
(void) memcpy(&pt, &pt_, sizeof(pt_)); // pt = pt_;
}
Run Code Online (Sandbox Code Playgroud)
这可以使用指针安全地完成
#include <memory>
struct Bar
{
std::unique_ptr<point> pPt_{ new point{ 0, 0 } };
const point& pt() const {
return *pPt_;
}
void move_x(int value) {
pPt_.reset(new point{ pt().x + value, pt().y });
}
};
Run Code Online (Sandbox Code Playgroud)
但是point它总是存储在堆上而不是存储在堆中Bar.
请注意,客户根本不关心point:
Foo foo;
foo.move_x(314); // (314, 0)
Bar bar;
bar.move_x(3141); // (3141, 0)
Run Code Online (Sandbox Code Playgroud)
这显然是未定义的行为.现在,"可以"这样做吗?当然,它可以,但只是在编译器不会抱怨的意义上.但是C++的一个方面就是因为编译器没有抱怨它并不意味着生成的代码能够正常工作.
有人写一些读取pt,调用move_x()然后再读取的代码只是时间问题pt.
一个现代的优化编译器将正确地假设因为代码正在读取const实例,它们的值不能改变,然后pt使用ptCPU寄存器中第一次读取时缓存的数据继续并优化第二次读取.
然后,倒霉的程序员将花费一周时间试图弄清楚为什么代码显然不会执行程序所说的应该做的事情.