检查子对象的地址是否在包含对象的边界内是否合法
Is it legal to check whether the address of a subobject lies within the bounds of a containing object
2 问题:
-
以下代码是否具有定义的行为?
-
是否有任何可能的 c++ 实现可以断言?
代码(c++11 及更高版本):
#include <cassert>
#include <utility>
#include <ciso646>
template<class T>
auto to_address(T* p) { return reinterpret_cast<unsigned char const*>(p); }
/// Test whether part is a sub-object of object
template<class Object, class Part>
bool is_within_object(Object& object, Part& part)
{
auto first = to_address(std::addressof(object)),
last = first + sizeof(Object);
auto p = to_address(std::addressof(part));
return (first <= p) and (p < last);
}
struct X
{
int a = 0;
int& get_a() { return a; }
int& get_b() { return b; }
private:
int b = 0;
};
int main()
{
X x;
assert(is_within_object(x, x.get_a()));
assert(is_within_object(x, x.get_b()));
}
请注意,a
和b
具有不同的访问说明符。
指针比较在 [expr.rel]/3-4 中定义:
将不相等指针与对象的比较定义如下:
- 如果两个指针指向同一数组的不同元素或其子对象,则指向具有较高下标的元素的指针会比较更大。
- 如果两个指针指向同一对象的不同非静态数据成员,或指向此类成员的子对象,则指向后面声明的成员的指针在两个成员具有相同的访问控制并且它们的类不是联合的情况下进行比较。
- 否则,两个指针的比较都不大于另一个指针。
如果两个操作数 p 和 q 比较相等,则 p<=q 和 p>=q 都产生 true,pq 都产生假。否则,如果指针 p 的比较大于指针 q,则 p>=q、p>q、q<=p 和 q=p,并且 q>p 都会产生 false。否则,未指定每个运算符的结果。
我们可以从中得出什么结论?
对象中相同类型的指针的总顺序,但指向不同对象或具有不同访问控制的不同子对象的指针没有顺序。由于缺乏指针的一般总顺序,is_within_object()
意义不大。在您希望它返回true
的情况下,它可以工作。在您希望它返回false
的情况下,这些运算符的结果未指定?这不是一个非常有用的结果。
也就是说,我们确实有一个巨大的漏洞,以[比较]的形式出现:
对于模板
less
、greater
、less_equal
和greater_equal
,任何指针类型的专用化都会产生一个严格的总顺序,这些专用化在这些专用化之间是一致的,并且也与内置运算符<
、>
、<=
、>=
强加的偏序一致。
因此,以下内容将得到明确定义:
template<class T>
auto byte_address(T& p) {
return reinterpret_cast<std::byte const*>(std::addressof(p));
}
template<class Object, class Part>
bool is_within_object(Object& object, Part& part)
{
auto first = byte_address(object);
auto last = first + sizeof(Object);
auto p = byte_address(part);
return std::less_equal<std::byte*>{}(first, p) &&
std::less<std::byte*>{}(p, last);
}
相关文章:
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 在这种情况下,java对象是否可以调用本机函数
- 堆分配的对象是否存在永不为空的唯一所有者?
- QFileSystemModel 对象是否会被删除?
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- 内联函数的函数本地静态对象是否在共享对象文件之间共享?
- 临时C++对象是否为左值?
- 为什么复制构造函数不需要检查输入对象是否指向自身?
- "this"指向的对象是否与 const 对象相同?
- 有什么方法可以检测我的类的对象是否在堆栈上创建
- 基类对象是否隐式添加到派生类中?
- 当 T 具有非平凡析构函数时,类类型 T 的对象是否可以常量初始化?
- 如何检查指针后面的对象是否有效或已删除?
- 谷神星求解器:残差函子使用的可变对象是否良好实践?还有什么其他选择
- 单一实例对象是否通过线程安全返回shared_ptr
- 对象是否保证在调用其成员函数之前被初始化
- 在另一个对象 B 中创建对象 A 时,对象 A 是否是对象 B 的本地对象,对象 A 是否会存在于对象 B 的实例化之外?
- 如何确定对象是否已分配成员
- 我们如何在c 中序列化或应对类的对象.是否有任何预定义的库
- 友元类对象是否可以在其成员函数中访问派生类对象的基类私有成员?