Reputation: 21186
How would i write the following with smart ptrs:
class App
{
public:
Project* GetProject();
SetProject( Project* project );
private:
Project* project;
}
Project* project = new Project();
App* app = new App();
app.SetProject( project );
Project* retrievedProject = app.GetProject();
I am mostly interested in the method paramters and return techniques... Is something like this correct?
class App
{
public:
void App::SetProject( unique_ptr<Project> project )
{
this->project.swap( project );
}
Project* App::GetProject() const
{
return this->project.get();
}
private:
unique_ptr< Project > project;
}
...
unique_ptr< Project > project( new Project() );
unique_ptr< App > app( new App() );
app.SetProject( project );
unique_ptr< Project > retrievedProject = app.GetProject();
This is related to this question: Should i stop using * pointers? - A few entry questions
I am slightly confused at what the rules are now... Thanks in advance!
Edit for minor question:
Galik, you had mentioned that it's rare that you want to declare Project outside of the function call and then pass it into with release... I have the following (for example):
unique_ptr<Project>project( new Project() );
project.Title = "Bob";
project.Type = PROJECTYPE.DISTRIBUTION;
project.Manager = manager;
app.SetProject( project.release() );
Is this perfectly normal? My issue is that I am actually creating tools for gaming and i'm worried that the constant flagging for deletion is going to be causing micro stutters as garbage collection is kicking in... Am I just worrying for worry sake?
Upvotes: 0
Views: 864
Reputation: 48675
The answer to this really depends on what you are wanting to do. You should use smart pointers to express ownership and you should not really be passing smart pointers about if you can at all help it.
If for example your App
class is supposed to take care of the various Project
objects and only give access to the Project
to outsiders then you should express that by returning a reference to the project.
That way several callers can access the internal Project
that is owned by the App
.
Rather like this:
class Project
{
public:
void do_stuff() {}
};
// This class is the Project Owner
// Meaning it is responsible for
// managing its life-time
class App
{
public:
// return a reference expressing the caller
// does not gain ownership merely access
Project& GetProject() { return *project; }
// replace configured Project
// accepting a std::unique_ptr expresses the fact that
// this function takes ownership of the Project
void SetProject(std::unique_ptr<Project> project) { this->project = std::move(project); }
private:
std::unique_ptr<Project> project;
};
int main()
{
App app; // don't make pointers if we don't have to
// project has ownership of the raw pointer
std::unique_ptr<Project> project(new Project());
// std::move() transfers ownership to the function's parameter
app.SetProject(std::move(project));
// get a reference to the internal Project
Project& retrievedProject = app.GetProject();
// work with configured Project
retrievedProject.do_stuff();
}
Upvotes: 1
Reputation: 56577
Here is a simple example with unique_ptr
#include <iostream>
#include <memory>
struct Project
{
~Project()
{
std::cout << "Destructor..." << std::endl;
}
};
class App
{
std::unique_ptr<Project> _uptr;
public:
// set _uptr to nullptr by default
App(std::unique_ptr<Project> uptr = nullptr): _uptr(std::move(uptr)){}
std::unique_ptr<Project> GetProject()
{
return std::move(_uptr);
};
void SetProject(std::unique_ptr<Project> project)
{
// need std::move, unique ownership
_uptr = std::move(project);
};
};
int main()
{
std::unique_ptr<Project> project(new Project);
std::unique_ptr<App> app(new App);
// need std::move, unique ownership
app->SetProject(std::move(project));
}
Upvotes: 1