C ++ - 指向具有相同地址但不同值的不同对象的另一个非静态成员的非静态void *成员

Posted

技术标签:

【中文标题】C ++ - 指向具有相同地址但不同值的不同对象的另一个非静态成员的非静态void *成员【英文标题】:C++ - non-static void* member pointing to another non-static member of different objects having same address but distinct value 【发布时间】:2020-05-18 07:23:09 【问题描述】:

这个问题标题不清楚,有点破。我尝试使用成员 void* 来存储另一个成员的地址。我无意中发现了一个奇怪的问题。在vector<T> 中创建了三个Object 对象。但是当我查看这三个val_addr 的值时,它们总是指向同一个地址,但显然每个val 总是唯一的。

class Object 

protected:
    int val 0;

    void *val_addr = nullptr;

    std::vector<Object> objs;

public:
    Object() = default;

    Object(int val) 
    
        this->val = val;
        this->val_addr = (void *) &this->val;
        std::cout << "val_addr: " << val_addr << "\n"; // always 0X123456 for example
    

    std::vector<Object>& get_objs() 
    
        return objs;
    

;

class Iterable : public Object 
public:
    Iterable(const std::set<int>& values)  // 1, 2, 3 inside values
        for (const auto & c : values) 
            this->objs.emplace_back(c);
        
    ;
;

【问题讨论】:

想想当Object 被复制或移动时会发生什么 您将参数 int val 的值复制到对象的字段 (int val 0) 中,但您并未将其指向新位置。然后,当您更新值时,您会读取字段的地址(不会随着您使用的对象而改变)。 另外,void* 演员表无效。 ***.com/questions/13875786/… 您可能不会期望不同的地址,因为每次调用 emplace_back 时可能会重新分配。当您从新创建的对象中打印出地址时,旧对象已被移动,并且先前打印的地址已更改 @S.M.我的理解是每次调用emplace_back,就会有一个临时对象,以后会被盗。但即使我使用push_back,结果也一样。 【参考方案1】:

任何指向对象成员的指针在向量扩展后都会失效。在放置新的向量元素并扩展向量后,您在对象构造函数中看到的地址无效。所以你在创建对象的那一刻看到了地址,而当你查看另一个对象内部的成员的地址时,之前的地址是无效的,可能无法进行比较。复制了前面的对象并更改了&amp;this-&gt;val,但this-&gt;val_addr 仍然包含旧的无效地址。您应该在复制构造函数中更新this-&gt;val_addr

class Object 
protected:
    int val 0;
    int *val_addr = nullptr;

public:
    Object() = default;

    Object(int val) 
    
        this->val = val;
        this->val_addr = &this->val;
        std::cout << "val_addr: " << val_addr << "\n";
    

    Object(const Object& obj) 
    
        this->val = obj->val;
        this->val_addr = &this->val;
        std::cout << "new val_addr: " << val_addr << "\n";
    

    std::vector<Object> &get_objs() const 
    
        return objs;
    
;

【讨论】:

我已经厌倦了resize() 以防止扩展,但结果相同。 只需添加复制构造函数即可。您总是在堆栈上的临时对象中打印地址。

以上是关于C ++ - 指向具有相同地址但不同值的不同对象的另一个非静态成员的非静态void *成员的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:创建具有相同键但不同值的对象

休眠错误:具有相同标识符值的不同对象已与会话关联

具有正确地址但具有另一个随机值的 C++ 指针?

检测具有相同名称但不同值的 Angular 绑定的更改?

Grails NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联

休眠:具有相同标识符值的不同对象已与会话相关联[重复]