我正在阅读关于严格别名的文章,但仍然有些模糊,我从来不确定定义/未定义行为的界限。我找到的最详细的文章集中在C语言上。因此,如果您能告诉我这是否允许以及自C++98/11以来发生了什么变化,那就太好了。
#include <iostream>
#include <cstring>
template <typename T> T transform(T t);
struct my_buffer {
char data[128];
unsigned pos;
my_buffer() : pos(0) {}
void rewind() { pos = 0; }
template <typename T> void push_via_pointer_cast(const T& t) {
*reinterpret_cast<T*>(&data[pos]) = transform(t);
pos += sizeof(T);
}
template <typename T> void pop_via_pointer_cast(T& t) {
t = transform( *reinterpret_cast<T*>(&data[pos]) );
pos += sizeof(T);
}
};
// actually do some real transformation here (and actually also needs an inverse)
// ie this restricts allowed types for T
template<> int transform<int>(int x) { return x; }
template<> double transform<double>(double x) { return x; }
int main() {
my_buffer b;
b.push_via_pointer_cast(1);
b.push_via_pointer_cast(2.0);
b.rewind();
int x;
double y;
b.pop_via_pointer_cast(x);
b.pop_via_pointer_cast(y);
std::cout << x << " " << y << '\n';
}
请不要过分关注可能存在的越界访问和可能没有必要编写类似代码的事实。我知道
char*
可以指向任何内容,但我也有一个指向char*
的T*
。也许还有其他我忽略的东西。这里有一个完整的示例,包括通过
memcpy
进行push/pop,据我所知,严格别名规则不会影响它。简而言之:上述代码是否存在未定义行为(暂时忽略越界访问),如果是,为什么?C++11或新标准有什么变化吗?