2

I've some trouble to display the value out from the function that returned pointer to structure. at the end q->b in main function does not return correctly from my function. I believed this should because of some initialize but don't know why ?

#include <iostream>
using namespace std;
struct Mystruct { int a, b; };

Mystruct *sum_struct(const Mystruct *x, const Mystruct *y)
{
    Mystruct ret= { 0,0 };
    ret.a = x->a + y->a;
    ret.b = x->b + y->b;
    cout << ret.a << "--" << ret.b << "--\n"; // able to cout here.
    return &ret;
}

int main()
{
    Mystruct o, p, *q;
    p.a = 1;    p.b = 2;
    o.a = 5;    o.b = 5;
    
    q = sum_struct(&o, &p);
    cout << q->a << "--" << q->b << "--\n"; // q->b showed -858993460 ( 0xFFFFFFFF)  = uninitialize value? 
}

somehow at the end its reported

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
iTum
  • 21
  • 2

2 Answers2

2

The main problem is that you're returning the address of the local variable named ret which is created on the stack and which will go out of scope once you return from that function. That is, you should not return the address of a local non-static object from a function.

Solution 1

One way would be to create the variable ret on the heap using new as shown below:

#include <iostream>

struct Mystruct { int a, b; };

Mystruct *sum_struct(const Mystruct *x, const Mystruct *y)
{
    Mystruct *ret= new Mystruct(); //note the use of keyword new here. Also note that ret is a pointer now
    ret->a = x->a + y->a; //note the use of ret->a instead of ret.a since ret is a pointer now
    ret->b = x->b + y->b; //note the use of ret->a instead of ret.a since ret is a pointer now
    std::cout << ret->a << "--" << ret->b << "--\n"; // Shows 6--7--
    return ret;
}

int main()
{
    Mystruct o, p, *q;
    p.a = 1;    p.b = 2;
    o.a = 5;    o.b = 5;
    
    q = sum_struct(&o, &p);
    std::cout << q->a << "--" << q->b << "--\n"; // shows 6--7--
    
    //use delete 
    delete q;
}

The output of the above program can be seen here. Note that instead of manually managing memory using new/delete, it would be better to use smart pointers.

Solution 2

Here instead of returning a pointer we just return a Mystruct object by value.

#include <iostream>

struct Mystruct { int a, b; };
//the function return a Mystruct object by value
Mystruct sum_struct(const Mystruct *x, const Mystruct *y)
{
    Mystruct ret{0,0}; 
    ret.a = x->a + y->a; 
    ret.b = x->b + y->b; 
    std::cout << ret.a << "--" << ret.b << "--\n"; //Shows 6--7--
    return ret; //return ret by value
}

int main()
{
    Mystruct o, p, q; //note q is not a pointer now
    p.a = 1;    p.b = 2;
    o.a = 5;    o.b = 5;
    
    q = sum_struct(&o, &p);
    std::cout << q.a << "--" << q.b << "--\n"; // shows 6--7--
    
    
}

The output of the above program can be seen here

Solution 3

You can use std::unique_ptr as shown below:

#include <iostream>
#include <memory>
struct Mystruct { int a, b; 
    
};

std::unique_ptr<Mystruct> sum_struct(const Mystruct *x, const Mystruct *y)
{
    std::unique_ptr<Mystruct> ret(new Mystruct()); //since  std::make_unique() does not exist in C++11. 

    //std::unique_ptr<Mystruct> ret= std::make_unique<Mystruct>(); //with C++14

    ret->a = x->a + y->a; 
    ret->b = x->b + y->b; 
    std::cout << ret->a << "--" << ret->b << "--\n"; //Shows 6--7--
    return ret;
}

int main()
{
    Mystruct o, p;
    p.a = 1;    p.b = 2;
    o.a = 5;    o.b = 5;
    
    std::unique_ptr<Mystruct> q = sum_struct(&o, &p);
    std::cout << q->a << "--" << q->b << "--\n"; // shows 6--7--
    
   //no need to use delete
}

Note that with C++14 you can use std::unique_ptr<Mystruct> ret= std::make_unique<Mystruct>(); instead of using std::unique_ptr<Mystruct> ret(new Mystruct()); since std::make_unique isn't available in C++11.

Jason
  • 36,170
  • 5
  • 26
  • 60
1

You are not allocating memory to this struct. It is created and removed once out of scope (once the function sum_struct is complete) To fix this you must explicitly allocate memory when you want to use it, and deallocate memory when you are done. It could look something like this in C:

Mystruct *sum_struct(const Mystruct *x, const Mystruct *y)
{
    Mystruct *ret = (Mystruct *)malloc(sizeof(Mystruct));
    ret->a = x->a + y->a;
    ret->b = x->b + y->b;
    cout << ret->a << "--" << ret->b << "--\n";
    return ret;
}

void dealloc_my_struct(const Mystruct *x)
{
    free(x);
}

or this in C++ (don't forget to #include <memory> for qunique_ptr):

std::unique_ptr<Mystruct> sum_struct(const Mystruct *x, const Mystruct *y)
{
    std::unique_ptr<Mystruct> ret = std::make_unique<Mystruct>(new Mystruct);
    ret->a = x->a + y->a;
    ret->b = x->b + y->b;
    std::cout << ret->a << "--" << ret->b << "--\n";
    return ret;
}

In c++ we don't need a destructor because std::unique_ptr's have a special feature where if they are freed, they free the data they point to.

Jacob Glik
  • 223
  • 3
  • 10
  • Yeah @user17732522 idk why I used malloc and free. it was like 2am and I thought this was C and not C++, my b – Jacob Glik Mar 03 '22 at 00:06