Access syntax for data pointer member to class pointer

Asked

Viewed 60 times

3

How does a pointer work when it comes to classes? For example:

class A{
public:
    int value;
};

int main(){
    A x;
    A* ptrx = &x;
    A** pptrx = &ptrx;

    //OK, retorna "value"
    std::cout << x.value << std::endl;

    //OK, o mesmo que "x.value"
    std::cout << ptrx->value << std::endl;

    //pptrx
    std::cout << /*pptrx?*/ << std::endl;
}

How do I return the value of x.value using the "pointer" pptrx?

2 answers

3

How do I return the value of x.value using the pptrx "pointer"?

I think there is already a good explanation above. But I will repeat next.

While doing some pointer tests I came across the following question: how a pointer to a pointer works when it comes to classes

About the title itself it is important to understand that the fact that they are pointers to class doesn’t make the slightest difference. It’s just like in C, where it wouldn’t make a difference being pointers to struct

Example

    A*      pA = nullptr;
    A**     p2A = nullptr;
    A***    p3A = nullptr;
    A****   p4A = nullptr;

In that case p3A is of what type? p3A is A***. So

  • *p3A is of the type A**
  • **p3A is of the type A*
  • and after all ***p3A is of the type A, an instance of class A.
  • And that’s what we always have: "take the * on one side and place on the other

Since you’re really doing tests and this one I think is a boring piece of C and C++ I’ll leave an example with plus testing. Less and less use is made every day in C++, but it will always be an essential concept for systems development languages when used for, for example, systems development :D

Your class A slightly altered

class A
{
public:
    int value;
    A() : A(42){};
    A(int v) : value(v){ cout << "Criada A com '" << value << "'\n";};
    ~A(){ std::cout << "Destruindo instancia de A(" << value << ")\n";};
};

To facilitate the example I added a constructor that accepts a int for a direct value, and created a destructor to see when the class can be destroyed in the middle of the program, in the case of dynamic allocation.

Test programs are for that after all

I will post some excerpts of the program and the corresponding excerpt in the output, then. At the end I will leave the whole program and the output throughout.

stretch 1

    A x;        std::cout << x.value << std::endl;
    A y(300);   std::cout << y.value << std::endl;
    A* p1 = nullptr;

This passage creates two A with values 42 (standard) and 300 and generates

exit

Criada A com '42'
42
Criada A com '300'
300

stretch 2

    p1 = &x;
    std::cout << p1->value << std::endl;

    p1 = new A(322);
    std::cout << p1->value << std::endl;

    std::cout << "vai destruir p1\n";
    delete p1;
    std::cout << "continuando...\n";

ago p1 point to x and displays the value. But then allocate a new p1 pointing to a new A value 322. Then delete p1 using delete and then you see the destructor being called.

exit

42
Criada A com '322'
322
vai destruir p1
Destruindo instancia de A(322)
continuando...

Section 3

    A** pp1 = new A*(nullptr);
    pp1 = &p1;
    p1 = &y;
    cout << "pp1 aponta para p1 que aponta para y(300). Valor = " << (**pp1).value << "\n";
    delete pp1; // libera *pp1;

Now declares pp1 as A** and makes him point to p1. p1 not pointing to anything, was targeted delete np stretch 2. But then the program does p1 point to y, and use **pp1 to print the value of y which is 300

Exit


pp1 aponta para p1 que aponta para y(300). Valor = 300

stretch 4

    *pp1 = &x; // reusa o ponteiro para apontar para o endereco de x
    (*pp1)->value = 18; // usa pp1 para alterar o valor de x
    cout << "Valor de x alterado para '" << x.value << "'\n";
    cout << "pp1 -> p1 -> x(18). Valor = " << (**pp1).value << "\n";
    cout << "ou de outro modo Valor = " << (*pp1)->value << "\n";
    cout << "ou ainda de outro modo Valor = " << (*(*pp1)).value << "\n";

pp was targeted by a delete then pointed to nothing. This section points to pp1 for x and uses the pointer to change the value of x to 18 and shows some ways to access

exit

Valor de x alterado para '18'
pp1 -> p1 -> x(18). Valor = 18
ou de outro modo Valor = 18
ou ainda de outro modo Valor = 18

final stretch

    // um ultimo exemplo usando pp1 para apontar para x e y
    pp1 = (A**)::operator new( 2 *sizeof(A*) );
    pp1[0] = &y;
    pp1[1] = &x;
    cout << "\nx(" << x.value << ")\n";
    cout << "y(" << y.value << ")\n";
    cout << "Acessando os valores de x e y atraves do vetor\n\
de ponteiros para ponteiros para a classe A:\n\
Valores de y e x: (" <<
        pp1[0]->value << "," <<
        pp1[1]->value << 
        ")\n";
    delete pp1;
    cout << "\nFim\n";

This part has the face of a C program, but uses pp1 that is A** to create two pointers and access the values of x and y. Nothing special, considering that is more or less what happens with every program in C++ to create the list of parameters for int main( int argc, char*[] argv).

Pointers are allocated, point to instances x and y of A and are used to display values via cout. Then the pointers are released and the program ends. Only then x and y are destroyed, which is clear at the exit because the message "End" appears before the destructors of x and y

exit

x(18)
y(300)
Acessando os valores de x e y atraves do vetor
de ponteiros para ponteiros para a classe A:
Valores de y e x: (300,18)

Fim
Destruindo instancia de A(300)
Destruindo instancia de A(18)

The complete program

#include <iostream>
using namespace std;
class A
{
public:
    int value;
    A() : A(42){};
    A(int v) : value(v){ cout << "Criada A com '" << value << "'\n";};
    ~A(){ std::cout << "Destruindo instancia de A(" << value << ")\n";};
};

int main(void)
{
    A x;        std::cout << x.value << std::endl;
    A y(300);   std::cout << y.value << std::endl;
    A* p1 = nullptr;
    
    p1 = &x;
    std::cout << p1->value << std::endl;

    p1 = new A(322);
    std::cout << p1->value << std::endl;

    std::cout << "vai destruir p1\n";
    delete p1;
    std::cout << "continuando...\n";

    A** pp1 = new A*(nullptr);
    pp1 = &p1;
    p1 = &y;
    cout << "pp1 aponta para p1 que aponta para y(300). Valor = " << (**pp1).value << "\n";
    delete pp1; // libera *pp1;

    *pp1 = &x; // reusa o ponteiro para apontar para o endereco de x
    (*pp1)->value = 18; // usa pp1 para alterar o valor de x
    cout << "Valor de x alterado para '" << x.value << "'\n";
    cout << "pp1 -> p1 -> x(18). Valor = " << (**pp1).value << "\n";
    cout << "ou de outro modo Valor = " << (*pp1)->value << "\n";
    cout << "ou ainda de outro modo Valor = " << (*(*pp1)).value << "\n";

    // um ultimo exemplo usando pp1 para apontar para x e y
    pp1 = (A**)::operator new( 2 *sizeof(A*) );
    pp1[0] = &y;
    pp1[1] = &x;
    cout << "\nx(" << x.value << ")\n";
    cout << "y(" << y.value << ")\n";
    cout << "Acessando os valores de x e y atraves do vetor\n\
de ponteiros para ponteiros para a classe A:\n\
Valores de y e x: (" <<
        pp1[0]->value << "," <<
        pp1[1]->value << 
        ")\n";
    delete pp1;
    cout << "\nFim\n";
    return 0;
}

the complete output

PS C:\src\CPP> g++ -o tst -Wall -std=c++2a tst.cpp
PS C:\src\CPP> ./tst
Criada A com '42'
42
Criada A com '300'
300
42
Criada A com '322'
322
vai destruir p1
Destruindo instancia de A(322)
continuando...
pp1 aponta para p1 que aponta para y(300). Valor = 300
Valor de x alterado para '18'
pp1 -> p1 -> x(18). Valor = 18
ou de outro modo Valor = 18
ou ainda de outro modo Valor = 18

x(18)
y(300)
Acessando os valores de x e y atraves do vetor
de ponteiros para ponteiros para a classe A:
Valores de y e x: (300,18)

Fim
Destruindo instancia de A(300)
Destruindo instancia de A(18)
PS C:\src\CPP> 

2


The operator ptrx->value it’s actually the same as (*ptrx).value, I’ll even put it in the code below. So to access a pointer you must dereference it this way, the arrow is only one facility, so use the normal shape and then you can even use the arrow normally for the other indirect.

#include <iostream>
using namespace std;

class A{
public:
    int value;
};

int main(){
    A x;
    x.value = 1;
    A* ptrx = &x;
    A** pptrx = &ptrx;
    std::cout << x.value << std::endl;
    std::cout << ptrx->value << std::endl;
    std::cout << (*ptrx).value << std::endl;
    std::cout << (*pptrx)->value << std::endl;
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.