Is this code causes undefined behavior? Or can i run into a problem with this? (copy the full class without functions, just variables with public modifier and modify the private memebers throw this pointer) example:
#include <iostream>
using namespace std;
class Point {
private:
int x;
int y;
public:
Point(int x, int y) {
this->x = x;
this->y = y;
}
void Print() {
cout << "(" << x << ", " << y << ")" << endl;
}
};
struct PointHack {
int x;
int y;
};
int main() {
Point a(4, 5);
a.Print();
((PointHack *) (&a))->x = 1;
((PointHack *) (&a))->y = 2;
a.Print();
return 0;
}
output:
(4, 5)
(1, 2)
(with the original member order, of course)
Despite your classes being layout compatible (see below), your code exhibits undefined behavior due to the fact that such pointer casts are prohibited by the C++ strict aliasing rules 1 .
But: replacing the casts with a union
makes the code standard-compliant; this is actually guaranteed to work in C++11:
#include <iostream>
using namespace std;
class Point {
private:
int x;
int y;
public:
Point(int x, int y) {
this->x = x;
this->y = y;
}
void Print() {
cout << "(" << x << ", " << y << ")" << endl;
}
};
struct PointHack {
int x;
int y;
};
union pu
{
Point p;
PointHack ph;
pu(int x, int y) : p(x, y) {}
};
int main() {
pu u(4,5);
u.p.Print();
u.ph.x=1;
u.ph.y=2;
u.p.Print();
return 0;
}
This comes from the fact that Point
and PointHack
are standard-layout classes 2 (C++11, §9 ¶7), and share a "common initial subsequence" (§9.2, ¶20); as such, if they both are stored in the same union (here pu
) it's permitted to "inspect the common initial part of any of them" 3 .
Still, this answer is mostly an exercise of style; don't exploit such tricks unless you are really forced to. C++ provides better means to access private members if necessary without brutally breaking the encapsulation - you have getters/setters, protected inheritance, friend classes, ... And in general, if you access private class members in ways not intended by your target class, you are potentially violating the assumptions of that class about how its data is modified, which can lead to erratic behavior of the code of its methods.
Notes:
ph
makes it the "active object" of the union
, and then p.Print()
is the one "inspecting" the "inactive" object. Yes, the posted code invokes undefined behavior. Don't do that.
If you want to see a really insane way that some people accomplish this unsavory goal, here you go: access private member using template trick
But really, don't do that.
PS: never use C-style casts in C++. Use static_cast, dynamic_cast, reinterpret_cast, and const_cast, as appropriate. C-style casts are needlessly unsafe.
i found the problem
/*code:*/
#include <stdio.h>
void check(short *h,long *k)
{
*h=5;
*k=6;
if (*h == 5)
printf("strict aliasing problem\n");
}
int main(void)
{
long k[1];
check((short *)k,k);
return 0;
}
/*
$ gcc -Wall -ansi -pedantic -O0 -o o0 asd.c
$ ./o0
/output: nothing/
$ gcc -Wall -ansi -pedantic -O2 -o o2 asd.c
$ ./o2
/output: strict aliasing problem/
*/
(same as in c++)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.