在 c++ 中进行指针数学运算班级:它“合法”吗?
啊海,海,
我想知道是否可以做如下的事情:
class SomeClass
{
int bar;
};
SomeClass* foo = new SomeClass();
int offset = &(foo->bar) - foo;
SomeClass* another = new SomeClass();
*(another+offset) = 3; // try to set bar to 3
只是好奇, 丹欧
Ah-hoi, hoi,
I'm wondering if it's ok to do something like the following:
class SomeClass
{
int bar;
};
SomeClass* foo = new SomeClass();
int offset = &(foo->bar) - foo;
SomeClass* another = new SomeClass();
*(another+offset) = 3; // try to set bar to 3
Just Curious,
Dan O
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我想从技术上讲它可能会成功。
然而,存在几个问题。酒吧是私人的。您正在混合不同类型的指针(指针算术依赖于指针类型:int* + 1 和 char* + 1 具有不同的结果,因为 int 和 char 具有不同的大小)。
您是否也考虑过指向成员的指针:
I suppose tecnically it might work out.
However, there are several problems. bar is private. You are mixing pointers of different types (pointer arithmetic relies on the pointer type: int* + 1 and char* + 1 have different results because int and char have a different size).
Have you also considered pointers to members:
这个想法对于 POD 类来说是可以的(其他人对示例代码中的错误也说过同样的话)。对于非 POD 类,您不一定仅通过对象指针的偏移量来识别成员。例如,考虑该成员是否是基类的一部分,或者等效地,如果您想要将偏移量应用于指向派生类的指针,但涉及多重继承或虚拟继承。
但是,您知道成员指针吗?
The idea is OK for POD classes (same things other people have said about the errors in your example code). For non-POD classes, you cannot necessarily identify a member just by an offset from the object pointer. Consider for example if the member is part of a base class, or equivalently if you want to apply the offset to a pointer to a derived class, but there is multiple- or virtual inheritance involved.
However, are you aware of pointers-to-member?
没什么问题,但是一不小心就很危险了。
另一方面,你的代码是错误的。 (another+offset) 的指针类型是什么?它实际上是指向 SomeClass 的指针,而不是 int,因此您至少应该将指针强制转换为 (int *):
偏移量是另一件需要注意的事情,因为它始终以指针指向的类型为单位。简而言之,当int长度为4个字节时,
(int *)
指针加1实际上会加4,所以更好在进行计算之前将任何指针强制转换为 (char *)。所以对于你的例子:
There's nothing wrong with it, but it's very dangerous if you're not careful.
On the other hand, your code is wrong. What's the pointer type of (another+offset)? It's actually a pointer to SomeClass, not an int, so you should at least cast the pointer to (int *):
The offset is another thing to watch out for, because it's always in units of the type the pointer points to. In short, when int is 4 bytes long, adding 1 to a
(int *)
pointer will actually add 4 to it, so it's better to cast any pointer to (char *) before doing calculations.So for your example:
您在示例中所做的事情并没有很好地使用指针。如果编译器做的事情与您期望的不同,它可能不起作用,并且可以使用正常方法以更少的源代码简单、高效地完成。
如果你有有效的使用,指针算术没有什么问题。不过,该语言尚未涵盖的内容并不多。
What you're doing in your example is not a good use of pointers. It may not work if the compiler does things differently than you expect, and it can be done just as simply, just as efficiently, and with less source code, using normal methods.
There's nothing wrong with pointer arithmetic if you have a valid use. There aren't very many not already covered by the language though.
没关系(通常你会为它定义一个宏,就像 Windows DDK 的 CONTAINING_RECORD 宏),但我会质疑为什么你在 C++ 中需要这个;通常你会在 C 中使用这些类型的技巧。
It's okay (usually you'd define a macro for it like the Windows DDK's CONTAINING_RECORD macro), but I'd question why you'd need this in C++; usually you use these types of tricks in C.
查看原始地址,这似乎可行,但对于语句中的初学者:
int offset = &(foo->bar) - foo;
您正在尝试减去不同的指针类型。因此,如果您将它们 reniterpret_cast 为 char * ,它应该会为您提供您正在寻找的内容。尽管这看起来太复杂且容易出错,没有任何用处。
Looking at the raw addresses, that seems like it would work, but for starters in your statement:
int offset = &(foo->bar) - foo;
You are trying to substract different pointer types. So if you reniterpret_cast them to char * it should give you what you are looking for.Although this seems too convoluted and error-prone to be any useful.