Reputation: 2619
I have a optional member in a class, which I want to return by value, via a method. Sample code:
#include <stdio.h>
#include <optional>
#include <iostream>
using namespace std;
class bar {
public:
int a;
bar(const bar &obj) {
a = obj.a;
}
};
class foo {
public:
void init(){
abc->a = 100;
}
optional<bar> get() {
return abc;
}
optional<bar> abc;
};
int main()
{
foo temp;
temp.init();
auto copied = temp.get();
cout << "Expected value is 100, got: " << copied->a;
return 0;
}
The code outputs some garbage value.
How may I achieve this?
From my understanding, optional stores a fully allocated memory for the underlying type (not just a reference), and while returning a optional variable, the copy constructor of the underlying type should kick in, which should copy the memory as-is to the new optional value being returned.
Upvotes: 0
Views: 1095
Reputation: 20579
You need to use the constructor of optional
to ensure that it contains an object: (assuming that the redundant copy constructor of bar
, which blocks it from being constructed, is removed)
foo()
: abc{bar{100}}
{
}
or, after the optional
has been created:
void init(){
abc = bar{100};
}
Otherwise, the optional
is kept in an empty state, and invoking ->
on an empty optional
results in undefined behavior. The copy constructor of optional
does not copy construct a contained object when the source is empty.
Upvotes: 4
Reputation: 36399
std::optional
is like a smart pointer, it defaults to a "null" value and accessing its members would therefore be undefined behaviour. You need to initialise it before use:
void init(){
abc = bar();
abc->a = 100;
}
Note that as it stands bar
isn't constructible other than via the copy constructor so you need to add a default constructor or a constructor that takes an int
argument or remove the unnecessary copy constructor.
Upvotes: 1