• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
blackfe2010

Question on boost::shared_ptr

15 posts in this topic

Hi,

I'm a beginner about boost.
And i try to write some code like:

[CODE]
#include "stdafx.h"
#include <boost/shared_ptr.hpp>
class A;
class B;
class A
{
public:
A() {};
boost::shared_ptr<B> a;
boost::shared_ptr<B> b;
};
class B
{
public:
B(){};
boost::shared_ptr<A> a;
boost::shared_ptr<A> b;
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.a=boost::shared_ptr<B>(&b);
a.b=boost::shared_ptr<B>(&b);
b.a=boost::shared_ptr<A>(&a);
b.b=boost::shared_ptr<A>(&a);
return 0;
}

[/CODE]
This program is crash.
Who can tell me what's happend? Edited by blackfe2010
0

Share this post


Link to post
Share on other sites
You should only use shared_ptr for dynamically allocated objects (allocated with new)! You are passing the address of objects created on the stack, that's why it crashes.
2

Share this post


Link to post
Share on other sites
Hi
It works, thx.

And how to convert "this" pointer to shared_ptr? Edited by blackfe2010
0

Share this post


Link to post
Share on other sites
I want do something like this:
[CODE]
class Manager
{
public:
void addComponent(boost::shared_ptr<Component> comp)
{
comp->m_Manager=this;
}
};
class Component
{
public
boost::shared_ptr<Manager> m_Manager;
};
[/CODE]
But how to let it work?
0

Share this post


Link to post
Share on other sites
To that derive your class from [url=http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/enable_shared_from_this.html]boost::enable_shared_from_this[/url] and call shared_from_this().
2

Share this post


Link to post
Share on other sites
Note that if you create multiple shared pointers to the same raw pointer (as noted above [b]never[/b] to do) they will each hold their own reference count therefore deleting before the other is out of scope. That is what you should always construct shared pointers with either shared_from_this() in the class or make_shared() elsewhere.
2

Share this post


Link to post
Share on other sites
[quote name='rip-off' timestamp='1351795690' post='4996264']
For completeness:[list]
[*]Because shared_ptr<> takes "ownership" of the passed pointer, it is incorrect to create two shared_ptr<>s from the same raw pointer
[*]It is incorrect to create cyclical loops via shared_ptr (at least if you actually want to prevent memory leaks). The relationship would need to be parent/child, with the child holding a non-shared pointer (e.g. a weak_ptr<> or possibly a raw pointer if you are confident) to the parent.
[/list]
[/quote]
So you means two or more shared_ptr can not point to the same raw pointer?
But i found some description about shared_ptr like "[url="http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/smart_ptr.htm"]Object ownership shared among multiple pointers.[/url]"
How to understand it?

And actually, I want do something like:
[CODE]
class Object
{
public:
void addComponents(boost::shared_ptr<Component> comp)
{
m_components.push_back(comp);
}

vector< boost::shared_ptr<Componnet> > m_components;
};
class ObjectManager : public boost::enable_shared_from_this<ObjectManager>
{
public:
void addComponent(boost::shared_ptr<Component> comp)
{
comp->m_Manager=shared_from_this();
m_allComponents.push_back(comp);
m_allObjects[some_id].addComponents(comp);
}

vector< boost::shared_ptr<Component> >m_allComponents;
vector< boost::shared_ptr<Object> > m_allObjects;
};
class Component
{
public
boost::shared_ptr<ObjectManager> m_Manager;
};
[/CODE]

Some Components in Object::m_components are point the same Component in ObjectManager::m_allcomponents.
So it is incorrect? Edited by blackfe2010
0

Share this post


Link to post
Share on other sites
[quote]
So you means two or more shared_ptr can not point to the same raw pointer?
[/quote]
Two shared pointers can share the same object. However, the way to do this is to create one shared_ptr<> to the object, and then copy the shared_ptr<>:
[code]
Example *example = new Example();
boost::shared_ptr<Example> one(example);
boost::shared_ptr<Example> two = one;
[/code]
Under the hood, this means that both shared_ptrs are aware of one another and the reference count of the object will be 2.

If you wite code like this:
[code]
Example *example = new Example();
boost::shared_ptr<Example> one(example);
boost::shared_ptr<Example> two(example);
[/code]
Then each shared_ptr assumes that it has exclusive ownership of the object. There will be two reference counts, both set to 1. When "one" goes out of scope, it will delete the object (provided no additional shared_ptr instances are created from it). Now two is left with a dangling pointer, and when it goes out of scope it will attempt to delete an invalid pointer.

[quote]
And actually, I want do something like ... So it is incorrect?
[/quote]
You appear to have a circular reference, so none of these shared_ptr instances will ever be destroyed. While you can break the cycle using weak_ptr<> or a raw pointer, I would advise you to also consider alternative designs that are less coupled to one another. For example, why does the Component class need to talk to the "Object Manager"? I would question the necessity of an "Object Manager" class.
2

Share this post


Link to post
Share on other sites
[quote name='rip-off' timestamp='1351848403' post='4996478']
why does the Component class need to talk to the "Object Manager"? I would question the necessity of an "Object Manager" class.
[/quote]

Because i want Component can communicate to other Components
[CODE]
class Component
{
public:
void sendMessage(string str)
{
m_objectManager->sendGlobalMessage(str);
}
};
class ObjectManager
{
pubic:
void sendGlobalMessage(string str)
{
for_each(m_allComponents.begin(),m_allComponents.end(),...);
}
};
[/CODE]

And about the weak_ptr<>, you means i should do something like:
[CODE]
class Component
{
boost::weak_ptr<ObjectManager> m_ojbectManager;
};
[/CODE]
right?
but weak_ptr haven't operator -> how can i use it? Edited by blackfe2010
0

Share this post


Link to post
Share on other sites
You have to lock a weak pointer which turns it into a shared pointer for the duration of the scope. For example std::shared_ptr<ObjectManager> manager = m_objectManager.lock();
1

Share this post


Link to post
Share on other sites
[quote name='blackfe2010' timestamp='1351784243' post='4996219']
I want do something like this:
[code]
class Manager
{
public:
void addComponent(boost::shared_ptr<Component> comp)
{
comp->m_Manager=this;
}
};
class Component
{
public
boost::shared_ptr<Manager> m_Manager;
};
[/code]
[/quote]

In such circumstances, since 'Component' does not "own" ([b]unique_ptr[/b]) or "share ownership" ([b]shared_ptr[/b]) of the [i]lifetime[/i] of Manager, Component should use a raw pointer. Raw pointers are not evil. Smart pointers don't replace raw pointers in [i]every[/i] circumstance, only the circumstances where the pointer needs to manage the [i]lifetime[/i] of the memory. In your example, you are just [i]accessing [/i]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, [i]raw pointer is the proper solution[/i]. 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. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
([size=2]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[/size])

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

shared_ptr [i]is[/i] (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.
[code]void addComponent(const boost::shared_ptr<Component> &comp)
{
this->components.push_back(comp);
this->components.back()->m_Manager = this;
}[/code]

Further, typedefs are awesome.
[code]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;
[/code]

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 [i]new[/i]-ing and [i]delete[/i]-ing properly, more accurately, [u]you[/u] are [i]new-[/i]ing, and the [u]smart pointer[/u] is [i]delete-[/i]ing. It'd be better (though not required), if you let smart pointers do the [i]new[/i]-ing and [i]delete[/i]-ing for you, so that a single API handles it entirely for the sake of consistency.

Enter [b]boost::make_shared[/b]. 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):
[b]1) [/b]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)
[b]2) [/b]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 [b]make_shared[/b]() to create your shared_ptrs. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[code]Component::sPtr mySharedPtr = boost::make_shared<Component>(/* Component's constructor arguments can go here, as if this was a normal constructor */);[/code]

[b]std::unique_ptr[/b] = I own this object, nobody else owns it _or_ uses it.
[b]std::shared_ptr[/b] = I own this object, possibly with shared ownership (through other std::shared_ptrs), and possibly with shared use (through weak_ptrs).
[b]std::weak_ptr[/b] = I don't own this object, I just use it.
[b]Regular raw pointer '*' [/b]= 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)

([size=2]The smart pointers in boost are probably in [b]std::tr1::[/b] namespace if you are not using C++11, or in [b]std::[/b] 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[/size])

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 ([size=2]talking about high level, not implementation details[/size]), 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. Edited by Servant of the Lord
2

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0