Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualServant of the Lord

Posted 02 November 2012 - 10:27 AM

I want do something like this:

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager=this;
  }
};
class Component
{
public
  boost::shared_ptr<Manager> m_Manager;
};


In such circumstances, since 'Component' does not "own" (unique_ptr) or "share ownership" (shared_ptr) of the lifetime of Manager, Component should use a raw pointer. Raw pointers are not evil. Smart pointers don't replace raw pointers in every circumstance, only the circumstances where the pointer needs to manage the lifetime of the memory. In your example, you are just accessing the memory.

If it is possible for Manager to be destructed before the components are destructed, then you should use a weak_ptr (if Manager is managed by a smart_ptr) - otherwise, if Manager's lifetime is guaranteed to exceed every Component lifetime, raw pointer is the proper solution. When adding the new tool "smart pointer" to your toolbox, you don't discard the previous tool "raw pointer", even if 90% of the old tool's duty is now taken over by the new tool. You don't throw away your screwdrivers when you buy a drill - there are many situations where a screwdriver is superior. Posted Image
(I have owned many a drill and many a screwdriver and frequently use them both - different tools for different jobs, even if their potential usage overlap 90% of the time)

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager = this;
  }
};
class Component
{
private:
	 friend class Manager;
	 Manager* m_Manager;
};

shared_ptr is (most likely) the proper choice for Manager's tracking of the Components (I'm assuming Manager has a vector of shared_ptr<Component>?). However, why unnecessarily copy the shared_ptr? Pass it to addComponent as a const ref.
void addComponent(const boost::shared_ptr<Component> &comp)
{
	 this->components.push_back(comp);
	 this->components.back()->m_Manager = this;
}

Further, typedefs are awesome.
class Component
{
	 //I use wPtr for 'weak pointer', uPtr for 'unique ptr', and I personally use 'Ptr' for shared_ptr, but sPtr would also be good.
	 //I don't typedef raw pointers, as the asterisk itself identifies it better than any single letter could: Component *ptr;
	 typedef boost::shared_ptr<Component> sPtr;
};

Component::sPtr mySharedPtr;

Furtherly further, one of the main points of smart pointers is that you don't need to handle the destruction of your data. A common rule of C++, is "Never new without delete", "never new[] without delete[]", "never malloc() without free()", etc...

Using smart pointers, while yes, technically you are new-ing and delete-ing properly, more accurately, you are new-ing, and the smart pointer is delete-ing. It'd be better (though not required), if you let smart pointers do the new-ing and delete-ing for you, so that a single API handles it entirely for the sake of consistency.

Enter boost::make_shared. More typing, but logically better as you ensure there is no chance for you to possibly mishandle the memory.
boost::make_shared() new()s the data, and returns it already in a shared_ptr, so you don't accidentally make the two deadly mistakes (both which you already made in this thread):
1) Passing stack data to a shared_ptr, mistakenly telling shared_ptr is is solely responsible for deleting the data (which isn't true, the stack would delete it)
2) Passing dynamic memory to two separate shared_ptrs. mistakenly telling each shared_ptr individually and separately that it is solely responsible for deleting the data (which isn't true, they both are responsible, but you accidentally told them they they were solely responsible).

Both avoided if you hold yourself to a single simple rule: Always use make_shared() to create your shared_ptrs. Posted Image
Component::sPtr mySharedPtr = boost::make_shared<Component>(/* Component's constructor arguments can go here, as if this was a normal constructor */);

std::unique_ptr = I own this object, nobody else owns it _or_ uses it.
std::shared_ptr = I own this object, possibly with shared ownership (through other std::shared_ptrs), and possibly with shared use (through weak_ptrs).
std::weak_ptr = I don't own this object, I just use it.
Regular raw pointer '*' = I don't own this object, I just use it (only use if the pointer's lifetime is guaranteed to be longer than the class containing it)

(The smart pointers in boost are probably in std::tr1:: namespace if you are not using C++11, or in std:: namespace if you are using C++11. They are basically the same, though they may have some minor changes. Boost is often a testing ground for new C++ Standard Library features)

weak_ptr can only be created from shared_ptrs. Weak pointers to memory not managed by a shared_ptr would basically be a raw pointer anyway (talking about high level, not implementation details), if it was allowed - which thankfully it isn't.

Enabling shared_from_this, is most likely not the correct thing you want to be using here (but it's hard to tell from only a small portion of code).
Using weak_ptrs to the Manager is also most likely the wrong choice.

Raw pointers are not evil, and this is one of the situations where they are the better solution.

#4Servant of the Lord

Posted 02 November 2012 - 10:22 AM

I want do something like this:

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager=this;
  }
};
class Component
{
public
  boost::shared_ptr<Manager> m_Manager;
};


In such circumstances, since 'Component' does not "own" (unique_ptr) or "share ownership" (shared_ptr) of the lifetime of Manager, Component should use a raw pointer. Raw pointers are not evil. Smart pointers don't replace raw pointers in every circumstance, only the circumstances where the pointer needs to manage the lifetime of the memory. In your example, you are just accessing the memory.

If it is possible for Manager to be destructed before the components are destructed, then you should use a weak_ptr (if Manager is managed by a smart_ptr) - otherwise, if Manager's lifetime is guaranteed to exceed every Component lifetime, raw pointer is the proper solution. When adding the new tool "smart pointer" to your toolbox, you don't discard the previous tool "raw pointer", even if 90% of the old tool's duty is now taken over by the new tool. You don't throw away your screwdrivers when you buy a drill - there are many situations where a screwdriver is superior. Posted Image
(I have owned many a drill and many a screwdriver and frequently use them both - different tools for different jobs, even if their potential usage overlap 90% of the time)

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager = this;
  }
};
class Component
{
private:
	 friend class Manager;
	 Manager* m_Manager;
};

shared_ptr is (most likely) the proper choice for Manager's tracking of the Components (I'm assuming Manager has a vector of shared_ptr<Component>?). However, why unnecessarily copy the shared_ptr? Pass it to addComponent as a const ref.
void addComponent(const boost::shared_ptr<Component> &comp)
{
	 this->components.push_back(comp);
	 this->components.back()->m_Manager = this;
}

Further, typedefs are awesome.
class Component
{
	 //I use wPtr for 'weak pointer', uPtr for 'unique ptr', and I personally use 'Ptr' for shared_ptr, but sPtr would also be good.
	 //I don't typedef raw pointers, as the asterisk itself identifies it better than any single letter could: Component *ptr;
	 typedef boost::shared_ptr<Component> sPtr;
};

Component::sPtr mySharedPtr;

Furtherly further, one of the main points of smart pointers is that you don't need to handle the destruction of your data. A common rule of C++, is "Never new without delete", "never new[] without delete[]", "never malloc() without free()", etc...

Using smart pointers, while yes, technically you are new-ing and delete-ing properly, more accurately, you are new-ing, and the smart pointer is delete-ing. It'd be better (though not required), if you let smart pointers do the new-ing and delete-ing for you, so that a single API handles it entirely for the sake of consistency.

Enter boost::make_shared. More typing, but logically better as you ensure there is no chance for you to possibly mishandle the memory.
boost::make_shared() new()s the data, and returns it already in a shared_ptr, so you don't accidentally make the two deadly mistakes (both which you already made in this thread):
1) Passing stack data to a shared_ptr, mistakenly telling shared_ptr is is solely responsible for deleting the data (which isn't true, the stack would delete it)
2) Passing dynamic memory to two separate shared_ptrs. mistakenly telling each shared_ptr individually and separately that it is solely responsible for deleting the data (which isn't true, they both are responsible, but you accidentally told them they they were solely responsible).

Both avoided if you hold yourself to a single simple rule: Always use make_shared() to create your shared_ptrs. Posted Image
Component::sPtr mySharedPtr = boost::make_shared<Component>(/* Component's constructor arguments can go here, as if this was a normal constructor */);

std::unique_ptr = I own this object, nobody else owns it _or_ uses it.
std::shared_ptr = I own this object, possibly with shared ownership (through other std::shared_ptrs), and possibly with shared use (through weak_ptrs).
std::weak_ptr = I don't own this object, I just use it.
Regular raw pointer '*' = I don't own this object, I just use it (only use if the pointer's lifetime is guaranteed to be longer than the class containing it)

(The smart pointers in boost are probably in std::tr1:: namespace if you are not using C++11, or in std:: namespace if you are using C++11. They are basically the same, though they may have some minor changes. Boost is often a testing ground for new C++ Standard Library features)

weak_ptr can only be created from shared_ptrs. Weak pointers to memory not managed by a shared_ptr would basically be a raw pointer anyway (talking about high level, not implementation details), if it was allowed - which thankfully it isn't.

#3Servant of the Lord

Posted 02 November 2012 - 10:21 AM

I want do something like this:

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager=this;
  }
};
class Component
{
public
  boost::shared_ptr<Manager> m_Manager;
};


In such circumstances, since 'Component' does not "own" (unique_ptr) or "share ownership" (shared_ptr) of the lifetime of Manager, Component should use a raw pointer. Raw pointers are not evil. Smart pointers don't replace raw pointers in every circumstance, only the circumstances where the pointer needs to manage the lifetime of the memory. In your example, you are just accessing the memory.

If it is possible for Manager to be destructed before the components are destructed, then you should use a weak_ptr (if Manager is managed by a smart_ptr) - otherwise, if Manager's lifetime is guaranteed to exceed every Component lifetime, raw pointer is the proper solution. When adding the new tool "smart pointer" to your toolbox, you don't discard the previous tool "raw pointer", even if 90% of the old tool's duty is now taken over by the new superior tool. You don't throw away your screwdrivers when you buy a drill - there are many situations where a screwdriver is superior. Posted Image
(I have owned many a drill and many a screwdriver and frequently use them both - different tools for different jobs, even if their potential usage overlap 90% of the time)

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager = this;
  }
};
class Component
{
private:
	 friend class Manager;
	 Manager* m_Manager;
};

shared_ptr is (most likely) the proper choice for Manager's tracking of the Components (I'm assuming Manager has a vector of shared_ptr<Component>?). However, why unnecessarily copy the shared_ptr? Pass it to addComponent as a const ref.
void addComponent(const boost::shared_ptr<Component> &comp)
{
	 this->components.push_back(comp);
	 this->components.back()->m_Manager = this;
}

Further, typedefs are awesome.
class Component
{
	 //I use wPtr for 'weak pointer', uPtr for 'unique ptr', and I personally use 'Ptr' for shared_ptr, but sPtr would also be good.
	 //I don't typedef raw pointers, as the asterisk itself identifies it better than any single letter could: Component *ptr;
	 typedef boost::shared_ptr<Component> sPtr;
};

Component::sPtr mySharedPtr;

Furtherly further, one of the main points of smart pointers is that you don't need to handle the destruction of your data. A common rule of C++, is "Never new without delete", "never new[] without delete[]", "never malloc() without free()", etc...

Using smart pointers, while yes, technically you are new-ing and delete-ing properly, more accurately, you are new-ing, and the smart pointer is delete-ing. It'd be better (though not required), if you let smart pointers do the new-ing and delete-ing for you, so that a single API handles it entirely for the sake of consistency.

Enter boost::make_shared. More typing, but logically better as you ensure there is no chance for you to possibly mishandle the memory.
boost::make_shared() new()s the data, and returns it already in a shared_ptr, so you don't accidentally make the two deadly mistakes (both which you already made in this thread):
1) Passing stack data to a shared_ptr, mistakenly telling shared_ptr is is solely responsible for deleting the data (which isn't true, the stack would delete it)
2) Passing dynamic memory to two separate shared_ptrs. mistakenly telling each shared_ptr individually and separately that it is solely responsible for deleting the data (which isn't true, they both are responsible, but you accidentally told them they they were solely responsible).

Both avoided if you hold yourself to a single simple rule: Always use make_shared() to create your shared_ptrs. Posted Image
Component::sPtr mySharedPtr = boost::make_shared<Component>(/* Component's constructor arguments can go here, as if this was a normal constructor */);

std::unique_ptr = I own this object, nobody else owns it _or_ uses it.
std::shared_ptr = I own this object, possibly with shared ownership (through other std::shared_ptrs), and possibly with shared use (through weak_ptrs).
std::weak_ptr = I don't own this object, I just use it.
Regular raw pointer '*' = I don't own this object, I just use it (only use if the pointer's lifetime is guaranteed to be longer than the class containing it)

(The smart pointers in boost are probably in std::tr1:: namespace if you are not using C++11, or in std:: namespace if you are using C++11. They are basically the same, though they may have some minor changes. Boost is often a testing ground for new C++ Standard Library features)

weak_ptr can only be created from shared_ptrs. Weak pointers to memory not managed by a shared_ptr would basically be a raw pointer anyway (talking about high level, not implementation details), if it was allowed - which thankfully it isn't.

#2Servant of the Lord

Posted 02 November 2012 - 10:19 AM

I want do something like this:

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager=this;
  }
};
class Component
{
public
  boost::shared_ptr<Manager> m_Manager;
};


In such circumstances, since 'Component' does not "own" (unique_ptr) or "share ownership" (shared_ptr) of the lifetime of Manager, Component should use a raw pointer. Raw pointers are not evil. Smart pointers don't replace raw pointers in every circumstance, only the circumstances where the pointer needs to manage the lifetime of the memory. In your example, you are just accessing the memory.

If it is possible for Manager to be destructed before the components are destructed, then you should use a weak_ptr (if Manager is managed by a smart_ptr) - otherwise, if Manager's lifetime is guaranteed to exceed every Component lifetime, raw pointer is the proper solution. When adding the new tool "smart pointer" to your toolbox, you don't discard the previous tool "raw pointer", even if 90% of the old tool's duty is now taken over by the new superior tool. You don't throw away your screwdrivers when you buy a drill - there are many situations where a screwdriver is superior. Posted Image
(I have owned many a drill and many a screwdriver and frequently use them both - different tools for different jobs, even if their potential usage overlap 90% of the time)

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager = this;
  }
};
class Component
{
private:
	 friend class Manager;
	 Manager* m_Manager;
};

shared_ptr is (most likely) the proper choice for Manager's tracking of the Components (I'm assuming Manager has a vector of shared_ptr<Component>?). However, why unnecessarily copy the shared_ptr? Pass it to addComponent as a const ref.
void addComponent(const boost::shared_ptr<Component> &comp)
{
	 this->components.push_back(comp);
	 this->components.back()->m_Manager = this;
}

Further, typedefs are awesome.
class Component
{
	 //I use wPtr for 'weak pointer', uPtr for 'unique ptr', and I personally use 'Ptr' for shared_ptr, but sPtr would also be good.
	 //I don't typedef raw pointers, as the asterisk itself identifies it better than any single letter could: Component *ptr;
	 typedef boost::shared_ptr<Component> sPtr;
};

Component::sPtr mySharedPtr;

Furtherly further, one of the main points of smart pointers is that you don't need to handle the destruction of your data. A common rule of C++, is "Never new without delete", "never new[] without delete[]", "never malloc() without free()", etc...

Using smart pointers, while yes, technically you are new-ing and delete-ing, more accurately, you are new-ing, and smart pointer is delete-ing. It'd be better (though not required), if you let smart pointers do the new-ing and delete-ing for you, so that API handles it entirely.

Enter boost::make_shared. More typing, but logically better as you ensure there is no chance for you to possibly mishandle the memory.
boost::make_shared() new()s the data, and returns it already in a shared_ptr, so you don't accidentally make the two deadly mistakes (both which you already made in this thread):
1) Passing stack data to a shared_ptr, mistakenly telling shared_ptr is is solely responsible for deleting the data (which isn't true, the stack would delete it)
2) Passing dynamic memory to two seperate shared_ptrs. mistakenly telling each shared_ptr individually and seperately that it is solely responsible for deleting the data (which isn't true, they both are responsible, but you accidentally told them they they were solely responsible).

Both avoided if you hold yourself to a single simple rule: Always use make_shared() to create your shared_ptrs. Posted Image
Component::sPtr mySharedPtr = boost::make_shared<Component>(/* Component's constructor arguments can go here, as if this was a normal constructor */);

std::unique_ptr = I own this object, nobody else owns it _or_ uses it.
std::shared_ptr = I own this object, possibly with shared ownership (through other std::shared_ptrs), and possibly with shared use (through weak_ptrs).
std::weak_ptr = I don't own this object, I just use it.
Regular raw pointer '*' = I don't own this object, I just use it (only use if the pointer's lifetime is guaranteed to be longer than the class containing it)

(The smart pointers in boost are probably in std::tr1:: namespace if you are not using C++11, or in std:: namespace if you are using C++11. They are basically the same, though they may have some minor changes. Boost is often a testing ground for new C++ Standard Library features)

weak_ptr can only be created from shared_ptrs. Weak pointers to memory not managed by a shared_ptr would basically be a raw pointer anyway (talking about high level, not implementation details), if it was allowed - which thankfully it isn't.

#1Servant of the Lord

Posted 02 November 2012 - 10:18 AM

I want do something like this:

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
	comp->m_Manager=this;
  }
};
class Component
{
public
  boost::shared_ptr<Manager> m_Manager;
};


In such circumstances, since 'Component' does not "own" (unique_ptr) or "share ownership" (shared_ptr) of the lifetime of Manager, Component should use a raw pointer. Raw pointers are not evil. Smart pointers don't replace raw pointers in every circumstance, only the circumstances where the pointer needs to manage the lifetime of the memory. In your example, you are just accessing the memory.

If it is possible for Manager to be destructed before the components are destructed, then you should use a weak_ptr (if Manager is managed by a smart_ptr) - otherwise, if Manager's lifetime is guaranteed to exceed every Component lifetime, raw pointer is the proper solution. When adding the new tool "smart pointer" to your toolbox, you don't discard the previous tool "raw pointer", even if 90% of the old tool's duty is now taken over by the new superior tool. You don't throw away your screwdrivers when you buy a drill - there are many situations where a screwdriver is superior. Posted Image
(I have owned many a drill and many a screwdriver and frequently use them both - different tools for different jobs, even if their potential usage overlap 90% of the time)

class Manager
{
public:
  void addComponent(boost::shared_ptr<Component> comp)
  {
    comp->m_Manager = this;
  }
};
class Component
{
private:
     friend class Manager;
	 Manager* m_Manager;
};

shared_ptr is (most likely) the proper choice for Manager's tracking of the Components (I'm assuming Manager has a vector of shared_ptr<Component>?). However, why unnecessarily copy the shared_ptr? Pass it to addComponent as a const ref.
void addComponent(const boost::shared_ptr<Component> &comp)
{
     this->components.push_back(comp);
     this->components.back()->m_Manager = this;
}

Further, typedefs are awesome.
class Component
{
     //I use wPtr for 'weak pointer', uPtr for 'unique ptr', and I personally use 'Ptr' for shared_ptr, but sPtr would also be good.
     //I don't typedef raw pointers, as the asterisk itself identifies it better than any single letter could: Component *ptr;
     typedef boost::shared_ptr<Component> sPtr;
};

Component::sPtr mySharedPtr;

Furtherly further, one of the main points of smart pointers is that you don't need to handle the destruction of your data. A common rule of C++, is "Never new without delete", "never new[] without delete[]", "never malloc() without free()", etc...

Using smart pointers, while yes, technically you are new-ing and delete-ing, more accurately, you are new-ing, and smart pointer is delete-ing. It'd be better (though not required), if you let smart pointers do the new-ing and delete-ing for you, so that API handles it entirely.

Enter boost::make_shared. More typing, but logically better as you ensure there is no chance for you to possibly mishandle the memory.
boost::make_shared() new()s the data, and returns it already in a shared_ptr, so you don't accidentally make the two deadly mistakes (both which you already made in this thread):
1) Passing stack data to a shared_ptr, mistakenly telling shared_ptr is is solely responsible for deleting the data (which isn't true, the stack would delete it)
2) Passing dynamic memory to two seperate shared_ptrs. mistakenly telling each shared_ptr individually and seperately that it is solely responsible for deleting the data (which isn't true, they both are responsible, but you accidentally told them they they were solely responsible).

Both avoided if you hold yourself to a single simple rule: Always use make_shared() to create your shared_ptrs. Posted Image
Component::sPtr mySharedPtr = boost::make_shared<Component>(/* Component's constructor arguments can go here, as if this was a normal constructor */);

std::unique_ptr = I own this object, nobody else owns it _or_ uses it.
std::shared_ptr = I own this object, possibly with shared ownership (through other std::shared_ptrs), and possibly with shared use (through weak_ptrs).
std::weak_ptr = I don't own this object, I just use it.
Regular raw pointer '*' = I don't own this object, I just use it (only use if the pointer's lifetime is guaranteed to be longer than the class containing it)

(The smart pointers in boost are probably in std::tr1:: namespace if you are not using C++11, or in std:: namespace if you are using C++11. They are basically the same, though they may have some minor changes. Boost is often a testing ground for new C++ Standard Library features)

weak_ptr can only be created from shared_ptrs. Weak pointers to memory not managed by a shared_ptr would basically be a raw pointer anyway (talking about high level, not implementation details), if it was allowed - which thankfully it isn't.

PARTNERS