Изменить объект, переданный указателем на функцию - PullRequest
2 голосов
/ 29 мая 2019

Мне нужно:

  1. Создать ссылку на объект.

  2. Передайте его функции, которая вызывает конструктор класса объекта, и произведите некоторые вычисления над объектом.

  3. Передача объекта в другую функцию, которая также делает с ним что-то другое.

Мой объект, который идет ко второй функции, всегда пуст.

Я немного знаю разницу между стеком и кучей памяти и использованием нового оператора, но не могу с этим справиться. Я не понимаю, почему g не меняется после завершения func1.

#include <iostream>

class Grid
{
    public:
        int a;

        Grid()
        {
            a = 2;
        }
};

void func1(Grid * g);
void func2(Grid * g);

int
main ()
{
    Grid g;
    func1(&g);
    func2(&g);
}

void
func1 (Grid * g)
{
    g = new Grid();
    g->a = 5;
}

void
func2 (Grid * g)
{
    std::cout << g->a << std::endl;
}

Как сделать вывод в func2 5, ведь теперь он 2?

Ответы [ 4 ]

3 голосов
/ 29 мая 2019

вот еще одна возможность использования указателей

Grid *  func1();
void func2(Grid * g);


int main ()
{

    Grid * g = func1();
    func2(g);
}


Grid * func1 ()
{
    Grid * g = new Grid();
    g->a = 5;
    return g;
}


void func2 (Grid * g)
{
    std::cout << g->a << std::endl;
}
3 голосов
/ 29 мая 2019

Если вы хотите использовать указатели для «передачи по ссылке», просто сделайте это:

void
func1 (Grid * g)
{
    g->a = 5;
}

void
func2 (const Grid * g)
{
    std::cout << g->a << std::endl;
}

int
main ()
{
    Grid g;
    func1(&g);
    func2(&g);
}

В настоящее время вы берете указатель (и помните, что сам указатель передается по значению),затем перезаписывает локальную копию этого указателя с указателем на новый, динамически размещаемый объект Grid.Вы устанавливаете свойство для этого объекта, а затем пропускаете его.

В C ++ вместо этого мы часто используем фактические ссылки, которые могут быть более понятными (хотя, возможно, и не такими ясными в месте вызова!):

void
func1 (Grid& g)
{
    g.a = 5;
}

void
func2 (const Grid& g)
{
    std::cout << g.a << std::endl;
}

int
main ()
{
    Grid g;
    func1(g);
    func2(g);
}

Что касается этого бита:

Передайте его функции, которая вызывает конструктор класса объекта

Объект уже создан.Вы можете скопировать-назначить из свежего временного объекта, если вы действительно хотите «сбросить» его таким образом:

void
func1 (Grid& g)
{
    g = Grid();
    g.a = 5;
}

Но я бы посоветовал пересмотреть, действительно ли вы хотите / нужно сбросить объект, какэтот.И, если вы делаете, возможно, хорошая reset() функция-член?

1 голос
/ 29 мая 2019

Чтобы помочь вам представить это, я напишу это так:

#include <iostream>

class Grid
{
    public:
        int a;

        Grid()
        {
            a = 2;
        }
};

void func1(uint64_t g);
void func2(uint64_t g);

int
main ()
{
    Grid g;
    func1((uint64_t)&g);
    func2((uint64_t)&g);
}

void
func1 (uint64_t g)
{
    g = (uint64_t)new Grid();
    ((Grid*)g)->a = 5;
}

void
func2 (uint64_t g)
{
    std::cout << ((Grid*)g)->a << std::endl;
}

Приведенный выше код будет работать точно так же, как и другой код (в 64-битной системе). Очевидно, что это ужасно, и приведенный выше код никогда не должен использоваться, но его написание таким образом может помочь вам понять указатели.

1 голос
/ 29 мая 2019

На самом деле, когда вы используете new, вы меняете значение указателя.

Но в любом случае, я думаю, вы можете сделать это намного проще.Например:

void func(Grid & g)
{
    g.a = 5;
}

РЕДАКТИРОВАТЬ: Конечно, вы должны позвонить func(), как это:

Grid gr;
func(gr);

Я надеюсь, что это может помочь;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...