简体   繁体   English

使用双指针为struct的成员赋值

[英]Assign value to member of struct using double pointer

I have a function that takes a double pointer to a struct and assigns a value. 我有一个函数,它接受一个结构的双指针并赋值。 However I get an "access violation writing location ..." when trying to access the member member1 . 但是,在尝试访问成员member1时,我收到“访问冲突写入位置...”。 This is my code: 这是我的代码:

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;
}

You just created a new mystruct pointer. 您刚刚创建了一个新的mystruct指针。 That means: 这意味着:

You get allocated a memory block, large enough to hold a address, and assign it to the pointer which is pointing to a pointer that points to a mystruct member. 您将获得一个内存块,大小足以容纳一个地址,并将其分配给指向指向mystruct成员的指针的指针。 That doesn't mean, that there is a valid address hold in the pointer which you expect to be pointing to a mystruct element. 这并不意味着,指针中有一个有效的地址保持,您希望指向一个mystruct元素。 Even more currently there isn't even a valid address, where the pointer to the pointer is pointing on, as you just assigned a valid memory area to it, what doesn't mean there is a usefull address stored in. 甚至更多的是,甚至没有一个有效的地址,指向指针的指针指向,因为你刚刚给它分配了一个有效的存储区域,这并不意味着存储了一个有用的地址。

So at all, what you want is: 所以,你想要的是:

You want a pointer which has a valid memory block to store a address in of another pointer, which is pointing to a valid memory area, where is a (probably valid) mystruct stored in. 你想要一个具有有效内存块的指针来存储另一个指针的地址,该指针指向一个有效的内存区域,其中存储一个(可能是有效的) mystruct

What you are doing is: you are requesting a memory area where you COULD (what you aren't even doing) store a poitner to another pointer... and so on. 你正在做的是:你正在请求一个你可能存在的内存区域(你甚至没做什么)将一个poitner存储到另一个指针......等等。

so what you should do is: 所以你应该做的是:

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

I have a function that takes a double pointer 我有一个带双指针的函数

That's weird. 那真是怪了。 If you can, simplify it to take a reference: 如果可以,请简化它以参考:

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

mystruct foo;
bar(42, foo);

If you don't have control over the function, then you'll need an object at the end of the pointer trail: 如果您无法控制该函数,那么您将需要指针跟踪末尾的对象:

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

You can, of course, mess around with new if you really want to; 当然,你可以的,勾搭new ,如果你真的想; but that's almost certainly a bad idea. 但这几乎肯定是一个坏主意。

Your code allocates and leaks a pointer, but doesn't initialise it to point to a valid object; 您的代码分配并泄漏指针,但不会将其初始化为指向有效对象; so dereferencing it gives undefined behaviour. 因此解除引用它会产生未定义的行为。

This C-style function: 这个C风格的功能:

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

takes an argument of type mystruct* in order for changes made to object that foo points to to be visible to the caller . 采用类型为mystruct*的参数,以便对foo指向的对象所做更改 对调用者可见 However this function: 但是这个功能:

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

takes pointer to mystruct* (most likely) in order to to modify the pointer itself , ie in order for changes made to the pointer to be visible to the caller and thus probably meant to be used this way: 将指针指向mystruct* (最有可能)以便修改指针本身 ,即为了使指针所做更改对调用者可见,因此可能意味着以这种方式使用:

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

... yet usually it is reasonable to avoid dynamic allocation and passing pointers should be rather rarity than a common practice. ...但通常避免动态分配是合理的,并且传递指针应该比普通的做法更为罕见。 Prefer objects with automatic storage duration over the dynamically allocated ones and prefer passing by reference over passing by pointer (when possible). 首选自动存储持续时间超过动态分配对象的对象,更喜欢通过引用传递指针(如果可能)。

The other answers are good advice. 其他答案是很好的建议。 But also, if you have control over the bar function, and need to be able to change in bar to what object your mystruct * pointer points to (which is probably the reason why you have a double pointer in the first place), then the cleanest approach is to use the following signature for bar : 但是,如果你可以控制bar函数,并且需要能够将bar更改为你的mystruct *指针所指向的对象(这可能是你首先有一个双指针的原因),那么最干净的方法是使用以下签名bar

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

It passes by reference a pointer, so you are able to change to what object the pointer points to, without sacrificing readability of the code, for instance: 它通过引用传递指针,因此您可以更改为指针指向的对象,而不会牺牲代码的可读性,例如:

int main()
{
    mystruct * foo = new mystruct;
    bar(42, foo);
}

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

A complete usage scenario without memory leak could be: 没有内存泄漏的完整使用场景可能是:

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; 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM