0

我在 C++ 中有以下结构:

struct wrapper 
{
    // Param constructor
    wrapper(unsigned int _id, const char* _string1, unsigned int _year, 
         unsigned int _value, unsigned int _usage, const char* _string2)
         :
         id(_id), year(_year), value(_value), usage(_usage)
         {
             int len = strlen(_string1);
             string1 = new char[len + 1]();
             strncpy(string1, _string1, len);

             len = strlen(_string2);
             string2 = new char[len + 1]();
             strncpy(string2, _string2, len);
         };
    // Destructor
    ~wrapper()
         {
             if(string1 != NULL) 
                delete [] string1;
             if(string2 != NULL) 
                delete [] string2;
         }

    // Elements
    unsigned int     id;         
    unsigned int     year;       
    unsigned int     value;     
    unsigned int     usage; 
    char*            string1;    
    char*            string2;   
};

在 main.cpp 中,假设我为此结构的一个对象分配内存:

wrapper* testObj = new wrapper(125600, "Hello", 2013, 300, 0, "bye bye");

我现在可以使用指针算术和指向结构元素之一的指针来删除整个对象吗?

像这样的东西:

void*  ptr = &(testObj->string2);

ptr -= 0x14;

delete (wrapper*)ptr;

我已经测试了自己,显然它可以工作,但我不能 100% 确定这相当于delete testObj.

谢谢。

4

3 回答 3

3

从技术上讲,这样的代码可以工作(忽略wrapper testObj应该是wrapper* testObj并且偏移量不一定是这样的事实0x14,例如调试构建有时会填充结构,也许我错过了一些其他细节),但这是一个可怕的、可怕的想法。我怎么强调都不为过,这有多可怕。

而不是0x14你可以使用offsetof宏。

如果你喜欢在调试器的陪伴下过夜,当然,随意这样做。

我假设这个问题的原因是纯粹好奇是否可以使用指针算法从成员导航到父级,而不是你想在生产代码中真正做到这一点。请告诉我我是对的。

于 2013-04-23T15:22:50.723 回答
1

我现在可以使用指针算术和指向结构元素之一的指针来删除整个对象吗?

理论上,是的。

您提供的指针delete需要具有正确的值,并且该值是来自现有的指针变量还是以这种方式“调整”一个并不重要。

您还需要考虑指针的类型;如果不出意外,您应该char*在执行算术之前强制转换,以便您以单字节为单位移动。您当前的代码将无法编译,因为ISO C++ forbids incrementing a pointer of type 'void*'(a 有多大void?)。

但是,我建议根本不要这样做。0x14考虑到对齐和填充以及结构改变形状的潜力,您的幻数是不可靠的。

相反,存储一个指向实际对象的指针。也停止所有可怕的记忆混乱,并使用std::string. 目前,您缺少复制构造函数正在呈现一个令人讨厌的错误。

于 2013-04-23T15:29:45.717 回答
0

可以用指针算术来做这种事情。你是否应该是一个完全不同的故事。考虑一下这个宏(我知道...我知道...),它会给你一个结构的基地址,给定它的类型,结构成员的名称和指向该成员的指针:

#define ADDRESS_FROM_MEMBER(T, member, ptr) reinterpret_cast<T*>( \
  reinterpret_cast<unsigned char *>(ptr) - (ptrdiff_t)(&(reinterpret_cast<T*>(0))->member))
于 2013-04-23T15:43:17.193 回答