简体   繁体   English

在 C++ 中传递 arrays 个指针

[英]Passing arrays of pointers in C++

Not sure what I'm doing wrong here.不确定我在这里做错了什么。 I'm trying to add a new element and up until the function ends it appears to have worked.我正在尝试添加一个新元素,直到 function 结束它似乎已经起作用。 But once I try to access anything in it after I get a segmentation fault.但是一旦我在遇到分段错误后尝试访问其中的任何内容。

This is just sample code I'm using to try and figure out what I'm doing wrong, with console output to help determine current values.这只是我用来尝试找出我做错了什么的示例代码,使用控制台 output 来帮助确定当前值。

#include <iomanip>
#include <iostream>

using namespace std;


class foo
    {
    private:
    int z;
    public:
    foo(int);
    int getz();
    void setz(int);
    };

    foo::foo(int zz)
    {
        z = zz;
    }

    int foo::getz()
    {
        return z;
    }

    void foo::setz(int zz)
    {
        z = zz;
    }

void boo(foo** x, unsigned* n)
{
    foo** b = new foo*[3];

    for (int i=0; i<2; i++)
        b[i] = x[i];
    b[2] = new foo(5);
    cout << x[0]->getz() << x[1]->getz();
    delete[]x;
    x = b;
    cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
    b = nullptr;
    (*n)++;
}

int main() {
    
    foo** a = new foo*[2];
    unsigned s = 2;

    a[0] = new foo(1);
    a[1] = new foo(2);
    boo(a, &s);
    cout << s;
    cout << a[0]->getz();
    return 0;
}

The problem is, how you pass your array to your function "boo".问题是,如何将数组传递给 function “boo”。

As a general notice, please let me recap how we can use in/out parameters for functions.作为一般通知,请让我回顾一下我们如何使用函数的输入/输出参数。 As you may have heard, we can你可能听说过,我们可以

  • pass by value.按值传递。 A copy of the parameter will be made and the all assign.nets to such a variable, will not be available after the function returns.将制作参数的副本,并且分配给此类变量的所有 assign.net 在 function 返回后将不可用。
  • pass by pointer.通过指针。 In the called function the the pointers will be dereferenced.在被调用的 function 中,指针将被取消引用。 Basically this is also pass by value.基本上这也是按值传递。 But here the address will be passed.但是这里会传递地址。 And with dereferencing the address, the original value can be modified.通过取消引用地址,可以修改原始值。
  • pass by reference (advised method).通过引用传递(建议方法)。 A reference to the original variable will be passed to the function and evrything can be handled as if interacting directly with the original variable.对原始变量的引用将传递给 function 并且可以像直接与原始变量交互一样处理所有事情。

You are passing the foo** as value.您正在将 foo** 作为值传递。 That is the reason why it will not work.这就是它不起作用的原因。 Delete the parameter will work, but the assignment of x to b will not be visible to the outside world.删除参数会起作用,但是 x 对 b 的赋值将对外界不可见。 And after the function "boo" returns, a will be deleted.而function“boo”返回后,a会被删除。

Let us look at the good all "swap" example.让我们看一下所有“交换”的好例子。

// Call by value, will not work. "a" will be changed, but it is a copy
void swapv(int a, int b) {
    int temp = a;
    a = b;
    b = tmp;
}
// Call by address(via pointer) will work. Dereferencing is necessary
void swapp(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = tmp;
}
// Call by reference. Recommended solution. Will simply work with same variable names
void swapr(int &a, int &b) {
    int temp = a;
    a = b;
    b = tmp;
}

As you can see.如你看到的。 The passing by reference approach is most simple.通过引用传递方法是最简单的。

Again, what you do is passing "foo**" by value.同样,您所做的是按值传递“foo**”。 By the way, "n" is passed via pointer.顺便说一句,“n”是通过指针传递的。 If you use a typedef or using statement, it will get very obvious.如果您使用typedefusing语句,它将变得非常明显。

Look at the following piece of code using a using -alias statement.查看以下使用using -alias 语句的代码。

using fooPtrPtr = foo**;
using fooPtr = foo*;

void boo(fooPtrPtr x, unsigned* n)
{
    fooPtrPtr b = new fooPtr[3];

    for (int i = 0; i < 2; i++)
        b[i] = x[i];
    b[2] = new foo(5);
    cout << x[0]->getz() << x[1]->getz();
    delete[]x;
    x = b;
    cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
    b = nullptr;
    (*n)++;
}
int main() {

    fooPtrPtr a = new fooPtr[2];
    unsigned s = 2;

    a[0] = new foo(1);
    a[1] = new foo(2);
    boo(a, &s);
    cout << s;
    cout << a[0]->getz();
    return 0;
}

Now you can immediately see the problem.现在您可以立即看到问题所在。 You see immediately that "x" is passed by value to "boo".您会立即看到“x”按值传递给“boo”。


But this leads then directly to the recommended and easy solution.但这会直接导致推荐的简单解决方案。 Pass it by reference.通过引用传递它。 Like the below:像下面这样:

using fooPtrPtr = foo**;
using fooPtr = foo*;

void boo(fooPtrPtr& x, unsigned& n)
{
    fooPtrPtr b = new fooPtr[3];

    for (int i = 0; i < 2; i++)
        b[i] = x[i];
    b[2] = new foo(5);
    cout << x[0]->getz() << x[1]->getz();
    delete[]x;
    x = b;
    cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
    b = nullptr;
    n++;
}
int main() {

    fooPtrPtr a = new fooPtr[2];
    unsigned s = 2;

    a[0] = new foo(1);
    a[1] = new foo(2);
    boo(a, s);
    cout << s;
    cout << a[0]->getz();
    return 0;
}

With pointers and pointers to pointers, using or typedef will be very helpful.对于指针和指向指针的指针, usingtypedef将非常有帮助。

Very simple.很简单的。 And without using using the code will be not so easy to understand and could look like the below.如果不using ,代码将不会那么容易理解,并且可能如下所示。

One ampersand "&" after foo** solves the whole problem. foo**后的一个符号“&”解决了整个问题。

void boo(foo**& x, unsigned& n)
{
    foo** b = new foo*[3];

    for (int i = 0; i < 2; i++)
        b[i] = x[i];
    b[2] = new foo(5);
    cout << x[0]->getz() << x[1]->getz();
    delete[]x;
    x = b;
    cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
    b = nullptr;
    n++;
}
int main() {

    foo** a = new foo*[2];
    unsigned s = 2;

    a[0] = new foo(1);
    a[1] = new foo(2);
    boo(a, s);
    cout << s;
    cout << a[0]->getz();
    return 0;
}


And last but not least also the version with pass by address / via pointer.最后但并非最不重要的还有通过地址/通过指针传递的版本。 Then a lot of dereferencing is necessary, which makes code even harder to read:然后需要大量的取消引用,这使得代码更难阅读:

void boo(foo*** x, unsigned *n)
{
    foo** b = new foo*[3];

    for (int i = 0; i < 2; i++)
        b[i] = (*x)[i];
    b[2] = new foo(5);
    cout << (*x)[0]->getz() << (*x)[1]->getz();
    delete[](*x);
    *x = b;
    cout << (*x)[0]->getz() << ' ' << (*x)[1]->getz() << ' ' << (*x)[2]->getz();
    b = nullptr;
    (*n)++;
}
int main() {

    foo** a = new foo*[2];
    unsigned s = 2;

    a[0] = new foo(1);
    a[1] = new foo(2);
    boo(&a, &s);
    cout << s;
    cout << a[0]->getz();
    return 0;
}

We can also use aliases to make this a little more readable, but still clumsy.我们还可以使用别名使它更具可读性,但仍然很笨拙。

using fooPtrPtr = foo**;
using fooPtr = foo*;

void boo(fooPtrPtr* x, unsigned *n)
{
    fooPtrPtr b = new fooPtr [3];

    for (int i = 0; i < 2; i++)
        b[i] = (*x)[i];
    b[2] = new foo(5);
    cout << (*x)[0]->getz() << (*x)[1]->getz();
    delete[](*x);
    *x = b;
    cout << (*x)[0]->getz() << ' ' << (*x)[1]->getz() << ' ' << (*x)[2]->getz();
    b = nullptr;
    (*n)++;
}
int main() {

    fooPtrPtr a = new fooPtr[2];
    unsigned s = 2;

    a[0] = new foo(1);
    a[1] = new foo(2);
    boo(&a, &s);
    cout << s;
    cout << a[0]->getz();
    return 0;
}

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

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