使用指针算术和指向该结构的元素的指针释放该结构



我在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

谢谢。

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

可以用offsetof宏代替0x14

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

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

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

理论上,是的。

你给delete的指针需要有正确的值,无论这个值是来自一个现有的指针变量,还是通过这种方式"调整"一个指针变量,都没有关系。

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

然而,我建议根本不要这样做。你的神奇数字0x14是不可靠的,考虑到对齐和填充以及你的结构改变形状的可能性。

存储指向实际对象的指针。同时停止所有可怕的内存混乱,并使用std::string。目前,缺少复制构造函数导致了一个严重的错误。

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

#define ADDRESS_FROM_MEMBER(T, member, ptr) reinterpret_cast<T*>( 
  reinterpret_cast<unsigned char *>(ptr) - (ptrdiff_t)(&(reinterpret_cast<T*>(0))->member))

最新更新