【问题标题】:Doing pointer math in a c++ class: Is it "legit"?在 C++ 类中进行指针数学运算:它“合法”吗?
【发布时间】:2010-11-26 07:10:53
【问题描述】:

喂喂喂

我想知道是否可以执行以下操作:

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

只是好奇, 丹奥

【问题讨论】:

  • 请修正代码以便bar 可以在您访问它的地方访问。我们目前不知道您是否想让它成为结构或公共或其他东西。我认为回答你的问题很重要。
  • 我的惰性指针语法可能是一个更大的问题,私有/公共位......耸耸肩......下班后会尝试编辑。
  • 不,私人/公共的事情也很重要。它有助于确定课程是否为 POD,这会在重要方面影响答案。

标签: c++ pointers class pointer-arithmetic


【解决方案1】:

没关系(通常你会为它定义一个宏,如 Windows DDK 的 CONTAINING_RECORD 宏),但我会质疑为什么你需要在 C++ 中使用它;通常你会在 C 中使用这些类型的技巧。

【讨论】:

    【解决方案2】:

    没毛病,但一不小心就很危险。

    另一方面,您的代码是错误的。 (another+offset) 的指针类型是什么?它实际上是指向 SomeClass 的指针,而不是 int,因此您至少应该将指针转换为 (int *):

     *((int *)(another + offset)) = 3;
    

    偏移量是另一件需要注意的事情,因为它总是以指针指向的类型为单位。简而言之,当 int 为 4 字节长时,将 1 加到 (int *) 指针实际上会加 4,因此最好将任何指针强制转换为 (char * ) 在进行计算之前。

    所以对于你的例子:

    SomeClass* foo = new SomeClass();
    int offset = (char *)&(foo->bar) - (char *)foo;
    
    SomeClass* another = new SomeClass();
    *((int *)((char *)another+offset)) = 3; // try to set bar to 3
    

    【讨论】:

      【解决方案3】:

      查看原始地址,这似乎可行,但对于您声明中的初学者:int offset = &(foo->bar) - foo; 您正在尝试减去不同的指针类型。因此,如果您将它们 reniterpret_cast 转换为 char *,它应该会为您提供所需的内容。

      虽然这看起来太复杂且容易出错,没有任何用处。

      【讨论】:

        【解决方案4】:

        我想在技术上它可能会成功。

        但是,有几个问题。酒吧是私人的。您正在混合不同类型的指针(指针运算依赖于指针类型:int* + 1 和 char* + 1 具有不同的结果,因为 int 和 char 具有不同的大小)。

        您是否也考虑过指向成员的指针:

        #include <cassert>
        
        struct SomeClass
        {
           int bar;
        };
        
        int main() {
            int SomeClass::*mem_ptr = &SomeClass::bar;
            SomeClass foo;
            foo.*mem_ptr = 3;
            assert(foo.bar == 3);
        }
        

        【讨论】:

        • +1 Pointer-to-member 似乎是原始提问者所寻找的。​​span>
        • 指向成员的指针非常有趣,我认为它不会让我实现我正在考虑的设计(但这不是重点,这是对我提出的问题的一个很好的回答)。
        • 我发现的关于成员指针的唯一文档将它们称为指向成员函数的指针,获取成员变量的地址是新颖的。无论哪种方式,我都应该能够缓存指向成员函数或变量的指针并获得我想要的功能。谢谢! (顺便说一下,仍在寻找更多文档,现在只是阅读常见问题)。
        【解决方案5】:

        这个想法对于 POD 类来说是可以的(其他人对您的示例代码中的错误所说的话是一样的)。对于非 POD 类,您不一定只通过对象指针的偏移量来识别成员。例如,考虑成员是否是基类的一部分,或者等效地,如果您想将偏移量应用于指向派生类的指针,但涉及多重继承或虚拟继承。

        但是,您知道指向成员的指针吗?

        struct SomeClass
        {
            int bar;
        };
        
        // fieldtoset is a pointer-to-member
        int SomeClass::*fieldtoset = &SomeClass::bar;
        
        SomeClass* another = new SomeClass();
        // syntax works as if "*fieldtoset" is "bar" (the member variable referand)
        another->*fieldtoset = 3 // set bar to 3
        

        【讨论】:

        • +1 Pointer-to-member 似乎是原始提问者所寻找的。​​span>
        • 指向成员内容的指针很有趣,但可能不适用于我想要做的事情,最终我想我会使用单个对象将我的值写入并复制它我已经完成了。
        【解决方案6】:

        您在示例中所做的并不是很好地使用指针。如果编译器执行的操作与您预期的不同,它可能无法正常工作,并且可以使用常规方法同样简单、高效且源代码更少。

        如果你有一个有效的使用,指针算术没有错。不过,该语言尚未涵盖的内容并不多。

        【讨论】:

          猜你喜欢
          • 2011-07-05
          • 2011-04-30
          • 2014-01-01
          • 2013-08-24
          • 1970-01-01
          • 2011-08-18
          • 1970-01-01
          • 2011-05-06
          相关资源
          最近更新 更多