【问题标题】:Assign value to member of struct using double pointer使用双指针为结构成员赋值
【发布时间】:2013-10-07 07:31:45
【问题描述】:

我有一个函数,它接受一个指向结构的双指针并分配一个值。但是,当我尝试访问成员 member1 时,我得到一个“访问冲突写入位置 ...”。 这是我的代码:

struct mystruct{
  unsigned int member1;
  void * data;
};

int main(){

  mystruct **foo = new mystruct *;
  bar(foo);

}

void bar(unsigned int val, mystruct ** foo)
{
    (*foo)->member1 = val;
}

【问题讨论】:

  • 在 C++ 中忘记 **,相信我你不会失去任何东西。
  • 注意:我将 C 标记更改为 C++,因为他使用的是 new,但也许他想要 C 代码,而 jsut 不知道 new 不是 C 的一部分

标签: c++ pointers pass-by-reference pass-by-pointer


【解决方案1】:

这个 C 风格的函数:

void bar1(mystruct* foo) {
    foo->member1 = val;
}

采用mystruct* 类型的参数,以便foo 指向的对象所做的更改对调用者可见。但是这个函数:

void bar(unsigned int val, mystruct ** foo) {
    (*foo)->member1 = val;
}

获取指向mystruct* 的指针(很可能)以修改指针本身,即对指针所做的更改对调用者,因此可能意味着以这种方式使用:

mystruct* foo = new mystruct;
bar(&foo);

...但通常避免动态分配是合理的,并且传递指针应该比常见的做法更罕见。与动态分配的对象相比,更喜欢具有自动存储持续时间的对象,并且更喜欢通过引用传递而不是通过指针传递(如果可能)。

【讨论】:

    【解决方案2】:

    其他答案是很好的建议。但是,如果您可以控制 bar 函数,并且需要能够将 bar 更改为您的 mystruct * 指针指向的对象(这可能是您在第一个中使用双指针的原因地方),那么最干净的方法是对bar使用以下签名:

    void bar(unsigned int val, mystruct * &foo);
    

    它通过引用传递一个指针,因此您可以更改指针指向的对象,而不会牺牲代码的可读性,例如:

    int main()
    {
        mystruct * foo = new mystruct;
        bar(42, foo);
    }
    
    void bar(unsigned int val, mystruct * &foo)
    { 
        foo->member1 = val;
        foo = new mystruct;
    }
    

    没有内存泄漏的完整使用场景可能是:

    int main()
    {
        // allocate dynamically a mystruct whose member1 is equal to 1.
        mystruct * foo1 = new mystruct;
        mystruct * foo2 = foo1;
        foo1->member1 = 1;
    
        // pass by reference foo1
        bar(42, foo1);
        // here, foo1->member1 == 42 and foo2->member1 == 10
    
        // free memory
        delete foo1; // the one allocated in bar()
        delete foo2; // the one allocated in main()
    }
    
    void bar(unsigned int val, mystruct * &foo)
    { 
        // modify the object allocated in main()
        foo->member1 = 10;
    
        // allocate dynamically a mystruct, store its address in foo
        foo = new mystruct; 
        foo->member1 = val; 
    }
    

    【讨论】:

    • 我的回答也符合这种方式,它只是不通过引用来做,更多的是它按照 OP 提到的方式来做。但无论如何 +1 给你。
    • 是的,你的答案是我最喜欢 Liho 的答案,我已经 +1 了,但由于尽可能通过参考传递是一种很好的做法,我认为告诉 OP 如何在这种情况下做;-)
    • @Zaibis 但是你在某一点上是对的,我把“正确的方法”改成了“最干净的方法”。一切都是正确的;-)
    【解决方案3】:

    我有一个带有双指针的函数

    这很奇怪。如果可以,请简化它以供参考:

    void bar(unsigned int val, mystruct & foo) {
        foo.member1 = val;
    }
    
    mystruct foo;
    bar(42, foo);
    

    如果你无法控制函数,那么你需要在指针尾端有一个对象:

    mystruct foo;
    mystruct * pointless = &foo;
    bar(42, &pointless);
    

    当然,如果你真的想的话,你可以和new 混在一起;但这几乎可以肯定是个坏主意。

    您的代码分配并泄漏了一个指针,但没有将其初始化为指向一个有效对象;所以取消引用它会产生未定义的行为。

    【讨论】:

      【解决方案4】:

      您刚刚创建了一个新的 mystruct 指针。这意味着:

      你被分配了一个足够大的内存块来保存一个地址,并将它分配给指向一个指向mystruct成员的指针的指针。 这并不意味着,您希望指向mystruct 元素的指针中有一个有效的地址。更当前甚至没有有效地址,指向指针的指针指向的位置,因为您刚刚为其分配了一个有效的内存区域,但这并不意味着其中存储了一个有用的地址。

      所以,你想要的是:

      您需要一个具有有效内存块的指针来存储另一个指针的地址,该指针指向一个有效的内存区域,其中存储了一个(可能有效的)mystruct

      你正在做的是:你正在请求一个内存区域,你可以(你甚至没有做)将一个指针存储到另一个指针......等等。

      所以你应该做的是:

      mystruct **foo = new mystruct *;
      *foo = new mystruct;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-16
        • 1970-01-01
        • 2011-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多