Through a series of layers, I want to create an object inside a vector and then get the address to that object. This is producing a segment fault. I'm actually kind of stumped.. I am returning the address of the object created and should be setting the value of the pointer to that address.
#include <iostream>
#include <string>
#include <vector>
class Obj {
public:
std::string name;
};
class Container {
public:
Obj& CreateObj(std::string name);
std::vector<Obj> objs;
};
Obj& Container::CreateObj(std::string name){
Obj obj;
obj.name = name;
objs.push_back(obj);
std::cout << "Container: 0x" << &objs.back() << std::endl;
return objs.back();
}
class App {
public:
Container container;
void CreateObj(std::string name, Obj *&obj);
};
void App::CreateObj(std::string name, Obj *&obj){
std::cout << "App: 0x" << obj << std::endl;
*obj = container.CreateObj(name);
std::cout << "App: 0x" << obj << std::endl;
}
int main()
{
Obj *obj = 0;
std::cout << "Main: 0x" << obj << std::endl;
App app;
app.CreateObj("ok", obj);
std::cout << "Main: 0x" << obj << std::endl;
std::cout << obj->name;
}
I'm all for a "better" way to do this - the constraint is that I must retrieve that ptr/ref through a parameter.
I believe that the segmentation fault is occurring on the line
*obj = Container.CreateObj(name);
in the method App::CreateObj. The variable obj in main is a nullptr, which you then pass into 'Container.CreateObj'. When the line '*obj = Container.CreateObj(name);' executes, the program tries to copy construct the resulting object from 'Container.CreateObj(name)' to the memory at address 0, resulting in the segmentation fault. I think this is the way I would go about "fixing" the code, though I'm not exactly sure if this is what you want:
#include <vector>
#include <iostream>
#include <string>
#include <memory>
class Obj {
public:
std::string name;
};
class Container {
public:
Obj& CreateObj(std::string name);
std::vector<Obj> objs;
};
Obj& Container::CreateObj(std::string name){
Obj obj;
obj.name = name;
objs.push_back(obj);
std::cout << "Container: 0x" << &objs.back() << std::endl;·
return objs.back();
}
class App {
public:
Container container;
void CreateObj(std::string name, Obj *obj);
};
void App::CreateObj(std::string name, Obj *obj){
std::cout << "App: 0x" << obj << std::endl;
*obj = container.CreateObj(name);
std::cout << "App: 0x" << obj << std::endl;
}
int main()
{
std::unique_ptr<Obj> obj = std::make_unique<Obj>();
App app;
app.CreateObj("ok", obj.get());
std::cout << obj->name;
}
Another way you could tackle this is with std::variant
. This would allow you to either return a reference
to an Object
(using reference_wrapper
) or an error code.
#include <variant>
#include <functional>
struct Object
{
Object( std::string n )
: name { std::move( n ) } { }
std::string name;
};
using ObjectRef = std::reference_wrapper<Object>;
using ErrorCode = int;
using Either = std::variant<ErrorCode, ObjectRef>;
class Container
{
public:
Either CreateObject( std::string name );
std::vector<Object> objects;
};
Either Container::CreateObject( std::string name )
{
if ( name.compare( "bill" ) == 0 ) return -10;
return objects.emplace_back( std::move( name ) );
}
class App
{
public:
Container container;
Either CreateObject( std::string name );
};
Either App::CreateObject( std::string name )
{
return container.CreateObject( std::move( name ) );
}
int main( )
{
App app;
auto either{ app.CreateObject( "karen" ) };
if ( std::holds_alternative<ErrorCode>( either ) )
{
auto error{ std::get<ErrorCode>( either ) };
std::cerr << "Failed to create karen. Error code: " << error << '\n';
return error;
}
auto& karen{ std::get<ObjectRef>( either ).get( ) };
std::cout << karen.name << '\n';
either = app.CreateObject( "bill" );
if ( std::holds_alternative<ErrorCode>( either ) )
{
auto error{ std::get<ErrorCode>( either ) };
std::cerr << "Failed to create bill. Error code: " << error << '\n';
return error;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.