I've been programming C++ for a while now and I'm starting to doubt that the rule use references whenever possible should be applied everywhere.
Unlike this related SO post I'm interested in a different kind of thing.
In my experience the reference/pointer mix messes up your code:
std::vector<Foo *> &x = get_from_somewhere(); // OK? reference as return value
some_func_pass_by_ref(x); // OK reference argument and reference variable
some_func_by_pointer(x[4]); // OK pointer arg, pointer value
some_func_pass_elem_by_ref(*x[5]); // BAD: pointer value, reference argument
some_func_that_requires_vec_ptr(&x); // BAD: reference value, pointer argument
One option would be to replace & with * const like Foo & with Foo * const
void some_func_by_ref(const std::vector<Foo * const> * const); // BAD: verbose!
this way at least the traversals are gone. and me rewriting function headers is gone, because all arguments will be pointers... at the price of polluting the code with const instead of pointer arithmetic (mainly & and *).
I would like to know how and when you apply use references whenever possible rule.
considering:
minimal rewriting of function prototypes (i.e.: oh damn I need need to rewrite alot of prototypes because I want to put this referenced element into a container)
increasing readability
avoid application of * to transform Foo* to Foo& and vice versa
avoid excessive const usage as in * const
NOTES: one thing I figured is to use pointers whenever I intend to ever put the element into an STL container (see boost::ref)
I don't think this is something C++03 specific but C++11 solutions are fine if they can be backported to C++03 (i.e.: NRVO instead of move-semantics).
When should I use references in C++?
When you need to treat a variable like the object itself (most cases when you don't explicitly need pointers and don't want to take ownership of an object).
I would like to know how and when you apply use references whenever possible rule.
whenever possible, except when you need to:
work on the address (log the address, diagnose or write custom memory allocation, etc)
take ownership of parameter (pass by value)
respect an interface that requires a pointer (C interoperability code and legacy code).
Bjarne Stroustrup stated in his book that he introduced references to the language because operators needed to be called without making a copy of the object (that would mean "by pointer") and he needed to respect syntax similar to calling by value (that would mean "not by pointer") (and thus references were born).
In short, you should use pointers as little as possible:
if the value is optional ("can be null") then use a std::optional around it, not a pointer
if you need to take ownership of the value, receive parameter by value (not a pointer)
if you need to read a value without modifying it, receive parameter by const &
if you need to allocate dynamically or return newly/dynamically allocated object, transmit value by one of: std::shared_ptr, std::unique_ptr, your_raii_pointer_class_here - not by (raw) pointer
if you need to pass a pointer to C code, you should still use the std::xxx_ptr classes, and get the pointer using .get() for getting the raw pointer.
one thing I figured is to use pointers whenever I intend to ever put the element into an STL container (or can I get rid of this?)
You can use Boost Pointer Container library.
IMHO the rule stands because raw pointers are dangerous because ownership and destruction responsibility becomes rapidly unclear. Hence the multiple encapsulations around the concept (smart_ptr, auto_ptr, unique_ptr, ...).
First, consider using such encapsulations instead of raw pointer in your container.
Second, why do you need to put pointers in a container ? I mean, they're meant to contain full objects ; they have an allocator as template argument for precise memory allocation after all. Most of the time, you want pointers because you have an OO-approach making heavy use of polymorphism. You should reconsider this approach. For example you can replace:
struct Animal {virtual std::string operator()() = 0;};
struct Dog : Animal {std::string operator()() {return "woof";}};
struct Cat : Animal {std::string operator()() {return "miaow";}};
// can not have a vector<Animal>
By something like this, using Boost.Variant :
struct Dog {std::string operator()() {return "woof";}};
struct Cat {std::string operator()() {return "miaow";}};
typedef boost::variant<Dog, Cat> Animal;
// can have a vector<Animal>
This way when you add a new animal, you inherit nothing, you just add it to the variant.
You can also consider, a little bit more complicated, but far more generic, using Boost.Fusion :
struct Dog {std::string talk; Dog() : talk("wook"){}};
struct Cat {std::string talk; Cat() : talk("miaow"){}};
BOOST_FUSION_ADAPT_STRUCT(Dog, (std::string, talk))
BOOST_FUSION_ADAPT_STRUCT(Cat, (std::string, talk))
typedef boost::fusion::vector<std::string> Animal;
int main()
{
vector<Animal> animals;
animals.push_back(Dog());
animals.push_back(Cat());
using boost::fusion::at;
using boost::mpl::int_;
for(auto a : animals)
{
cout << at<int_<0>>(a) << endl;
}
}
This way you do not even modify an aggregate like variant nor the algorithms on animals, you just need to provide a FUSION_ADAPT matching the used algorithms prerequisites. Both versions (variant and fusion) let you define orthogonal object groups, a useful thing you can not do with inheritance trees.
The following ways seem reasonable dealing with this:
boost and C++11 have a class that can cheaply be used to store references in a container: Reference Wrapper
A good advice is to use the handle/body idiom more often instead of passing around raw pointers. This also solves the ownership issue of the memory that is governed by the reference or the pointer. Sean Parent from Adobe has pointed this out at a talk at going native 2013.
I chose to use the Handle/Body Idiom approach because it gives pointers automatically copy/assign behaviour while hiding the underlying implementation and ownership semantics. It also acts as kind of a compile time firewall reducing header file inclusion.
Related
Hy, I would like to ask a question that puzzles me.
I've a class like this:
class A {
private:
std::vector<Object*>* my_array_;
...
public
std::vector<Object*>& my_array(); // getter
void my_array(const std::vector<Object*>& other_array); // setter
};
I wanted to ask you, based on your experience, what is the correct way of implementing the setter and getter in a (possible) SAFE manner.
The first solution came to my mind is the following.
First, when I do implement the setter, I should:
A) check the input is not a referring to the data structure I already hold;
B) release the memory of ALL objects pointed by my_array_
C) copy each object pointed by other_array and add its copy to my_array_
D) finally end the function.
The getter may produce a copy of the inner array, just in case.
The questions are many:
- is this strategy overkilling?
- does it really avoid problems?
- somebody really uses it or are there better approaches?
I've tried to look for the answer to this question, but found nothing so particularly focused on this problem.
That of using smart pointers is a very good answer, i thank you both.. it seems I can not give "useful answer" to more than one so I apologize in advance. :-)
From your answers however a new doubt has raised.
When i use a vector containing unique_ptr to objects, I will have to define a deep copy constructor. Is there a better way than using an iterator to copy each element in the vector of objects, given that now we are using smart pointers?
I'd normally recommend not using a pointer to a vector as a member, but from your question it seems like it's shared between multiple instances.
That said, I'd go with:
class A {
private:
std::shared_ptr<std::vector<std::unique_ptr<Object> > > my_array_;
public
std::shared_ptr<std::vector<std::unique_ptr<Object> > > my_array(); // getter
void my_array(std::shared_ptr<std::vector<std::unique_ptr<Object> > > other_array); // setter
};
No checks necessary, no memory management issues.
If the inner Objects are also shared, use a std::shared_ptr instead of the std::unique_ptr.
I think you are overcomplicating things having a pointer to std::vector as data member; remember that C++ is not Java (C++ is more "value" based than "reference" based).
Unless there is a strong reason to use a pointer to a std::vector as data member, I'd just use a simple std::vector stored "by value".
Now, regarding the Object* pointers in the vector, you should ask yourself: are those observing pointers or are those owning pointers?
If the vector just observes the Objects (and they are owned by someone else, like an object pool allocator or something), you can use raw pointers (i.e. simple Object*).
But if the vector has some ownership semantics on the Objects, you should use shared_ptr or unique_ptr smart pointers. If the vector is the only owner of Object instances, use unique_ptr; else, use shared_ptr (which uses a reference counting mechanism to manage object lifetimes).
class A
{
public:
// A vector which owns the pointed Objects
typedef std::vector<std::shared_ptr<Object>> ObjectArray;
// Getter
const ObjectArray& MyArray() const
{
return m_myArray
}
// Setter
// (new C++11 move semantics pattern: pass by value and move from the value)
void MyArray(ObjectArray otherArray)
{
m_myArray = std::move(otherArray);
}
private:
ObjectArray m_myArray;
};
I'm not a very experienced c++ coder and this has me stumped. I am passing a object (created elsewhere) to a function, I want to be able to store that object in some array and then run through the array to call a function on that object. Here is some pseudo code:
void AddObject(T& object) {
object.action(); // this works
T* objectList = NULL;
// T gets allocated (not shown here) ...
T[0] = object;
T[0].action(); // this doesn't work
}
I know the object is passing correctly, because the first call to object.action() does what it should. But when I store object in the array, then try to invoke action() it causes a big crash.
Likely my problem is that I simply tinkered with the .'s and *'s until it compiled, T[0].action() compliles but crashes at runtime.
The simplest answer to your question is that you must declare your container correctly and you must define an appropriate assigment operator for your class. Working as closely as possible from your example:
typedef class MyActionableClass T;
T* getGlobalPointer();
void AddInstance(T const& objInstance)
{
T* arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **objects**
//whose first element we don't mind losing
//**copy** the instance we've received
arrayFromElsewhere[0] = objInstance;
//now invoke the action() method on our **copy**
arrayFromElsewhere[0].action();
}
Note the signature change to const reference which emphasizes that we are going to copy the original object and not change it in any way.
Also note carefully that arrayFromElsewhere[0].action() is NOT the same as objInstance.action() because you have made a copy — action() is being invoked in a different context, no matter how similar.
While it is obvious you have condensed, the condensation makes the reason for doing this much less obvious — specifying, for instance, that you want to maintain an array of callback objects would make a better case for “needing” this capability. It is also a poor choice to use “T” like you did because this tends to imply template usage to most experienced C++ programmers.
The thing that is most likely causing your “unexplained” crash is that assignment operator; if you don't define one the compiler will automatically generate one that works as a bitwise copy — almost certainly not what you want if your class is anything other than a collection of simple data types (POD).
For this to work properly on a class of any complexity you will likely need to define a deep copy or use reference counting; in C++ it is almost always a poor choice to let the compiler create any of ctor, dtor, or assignment for you.
And, of course, it would be a good idea to use standard containers rather than the simple array mechanism you implied by your example. In that case you should probably also define a default ctor, a virtual dtor, and a copy ctor because of the assumptions made by containers and algorithms.
If, in fact, you do not want to create a copy of your object but want, instead, to invoke action() on the original object but from within an array, then you will need an array of pointers instead. Again working closely to your original example:
typedef class MyActionableClass T;
T** getGlobalPointer();
void AddInstance(T& objInstance)
{
T** arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **pointers**
//whose first element we don't mind losing
//**reference** the instance we've received by saving its address
arrayFromElsewhere[0] = &objInstance;
//now invoke the action() method on **the original instance**
arrayFromElsewhere[0]->action();
}
Note closely that arrayFromElsewhere is now an array of pointers to objects instead of an array of actual objects.
Note that I dropped the const modifier in this case because I don’t know if action() is a const method — with a name like that I am assuming not…
Note carefully the ampersand (address-of) operator being used in the assignment.
Note also the new syntax for invoking the action() method by using the pointer-to operator.
Finally be advised that using standard containers of pointers is fraught with memory-leak peril, but typically not nearly as dangerous as using naked arrays :-/
I'm surprised it compiles. You declare an array, objectList of 8 pointers to T. Then you assign T[0] = object;. That's not what you want, what you want is one of
T objectList[8];
objectList[0] = object;
objectList[0].action();
or
T *objectList[8];
objectList[0] = &object;
objectList[0]->action();
Now I'm waiting for a C++ expert to explain why your code compiled, I'm really curious.
You can put the object either into a dynamic or a static array:
#include <vector> // dynamic
#include <array> // static
void AddObject(T const & t)
{
std::array<T, 12> arr;
std::vector<T> v;
arr[0] = t;
v.push_back(t);
arr[0].action();
v[0].action();
}
This doesn't really make a lot of sense, though; you would usually have defined your array somewhere else, outside the function.
I need a collection in which i can store heap-allocated objects having virtual functions.
I known about boost::shared_ptr, std::unique_ptr (C++11) and boost::ptr_(vector|list|map), but they doesn't solve duplicate pointer problem.
Just to describe a problem - i have a function which accepts heap-allocated pointer and stores it for future use:
void SomeClass::add(T* ptr)
{
_list.push_back(ptr);
}
But if i call add twice with same parameter ptr - _list will contain two pointers to same object and when _list is destructed multiple deletion of same object will occur.
If _list will count pointer which he stores and uses them at deletion time then this problem will be solved and objects will not be deleted multiple times.
So the question is:
Does somebody knows some library with collections (vector,list,map in essence) of pointer with auto-delete on destruction and support of reference counting?
Or maybe i can solve this problem using some other technique?
Update:
I need support of duplicate pointers. So i can't use std::set.
As Kerrek SB and Grizzly mentioned - it is a bad idea to use raw pointers in general and suggests to use std::make_shared and forget about instantiation via new. But this is responsibility of client-side code - not the class which i designs. Even if i change add signature (and _list container of course) to
void SomeClass::add(std::shared_ptr<T> ptr)
{
_list.push_back(ptr);
}
then somebody (who doesn't know about std::make_shared) still can write this:
SomeClass instance;
T* ptr = new T();
instance.add(ptr);
instance.add(ptr);
So this is not a full solution which i wait, but useful if you write code alone.
Update 2:
As an alternative solution i found a clonning (using generated copy constructor). I mean that i can change my add function like this:
template <typename R>
void SomeClass::add(const R& ref)
{
_list.push_back(new R(ref));
}
this will allow virtual method (R - class which extends some base class (interface)) calls and disallow duplicate pointers. But this solution has an overhead for clone.
Yes: std::list<std::shared_ptr<T>>.
The shared pointer is avaiable from <memory>, or on older platforms from <tr1/memory>, or from Boost's <boost/shared_ptr.hpp>. You won't need to delete anything manually, as the shared pointer takes care of this itself. You will however need to keep all your heap pointers inside a shared pointer right from the start:
std::shared_ptr<T> p(new T); // legacy
auto p = std::make_shared<T>(); // better
If you another shared pointer to the same object, make a copy of the shared pointer (rather than construct a new shared pointer from the underlying raw pointer): auto q = p;
The moral here is: If you're using naked pointers, something is wrong.
Realize that smart pointers are compared by comparing the underlying container. So you can just use a std::set of whatever smartpointer you prefer. Personally I use std::unique_ptr over shared_ptr, whenever I can get away with it, since it makes the ownership much clearer (whoever holds the unique_ptris the owner) and has much lower overhead too. I have found that this is enough for almost all my code. The code would look something like the following:
std::set<std::unique_ptr<T> > _list;
void SomeClass::add(T* ptr)
{
std::unique_ptr<T> p(ptr);
auto iter = _list.find(p);
if(iter == _list.end())
_list.insert(std::move(p));
else
p.release();
}
I'm not sure right now if that is overkill (have to check if insert is guaranteed not to do anything, if the insertion fails), but it should work. Doing this with shared_ptr<T> would look similar, although be a bit more complex, due to the lack of a relase member. In that case I would probably first construct a shared_ptr<T> with a do nothing deleter too pass to the call to find and then another shared_ptr<T> which is actually inserted.
Of course personally I would avoid doing this and always pass around smart pointers when the ownership of a pointer changes hands. Therefore I would rewrite SomeClass::add as void SomeClass::add(std::unique_ptr<T> ptr) or void SomeClass::add(std::shared_ptr<T> ptr) which would pretty much solve the problem of having multiple instances anyways (as long as the pointer is always wrapped).
I am programming in C++ more then 5 years, and have never met any place where reference of the variable is recommended to use except as a function argument (if you don't want to copy what you pass as your function argument). So could someone point cases where C++ variable reference is recommended (I mean it gives any advantage) to use.
As a return value of an opaque collection accessor/mutator
The operator[] of std::map returns a reference.
To shorten the text needed to reference a variable
If you miss old-school with Foo do ... statement (that's Pascal syntax), you can write
MyString &name = a->very->long_->accessor->to->member;
if (name.upcase() == "JOHN") {
name += " Smith";
}
another example of this can be found in Mike Dunlavey's answer
To state that something is just a reference
References are also useful in wrapper objects and functors--i.e. in intermediate objects that logically contact no members but only references to them.
Example:
class User_Filter{
std::list<User> const& stop_list;
public: Functor (std::list<User> const& lst)
: stop_list(lst) { }
public: bool operator()(User const& u) const
{ return stop_list.exists(u); }
};
find_if(x.begin(),x.end(),User_Filter(user_list));
The idea here that it's a compile error if you don't initialize a reference in constructor of such an object. The more checks in compile time--the better programs are.
Here's a case where it's handy:
MyClass myArray[N];
for (int i = 0; i < N; i++){
MyClass& a = myArray[i];
// in code here, use a instead of myArray[i], i.e.
a.Member = Value;
}
Use references wherever you want, pointers when you are forced to.
References and pointers share part of their semantics: they are an alias to an element that is not present. The main difference is with memory managements: references express clearly that you are not responsible for the resource. On the other hand, with pointers it is never really clear (unless you mean smart pointers): are you assumed to delete the pointer or will it be deleted externally?
You must use pointers when you must manage memory, want to allow for optional semantics or need to change the element referred to at a later time.
In the rest of cases, where you can use a reference or a pointer, references are clearer and should be preferred.
Now, as you point out, they are really not needed: you can always use pointers for all the reference uses (even parameter passing), but the fact that you can use a single tool for everything does not mean there are no better suited tools for the job.
I tend to use reference members instead of pointers for externally controlled non-optional construction parameters.
EDIT (added example):
Let's say that you have a database and a DAO class having the database as a dependency:
struct Database {};
struct PersonDao {
const Database &m_d;
PersonDao(const Database &d): m_d(d) {}
};
Furthermore, the scope of the database is controlled externally from the DAO:
int main() {
Database d;
PersonDao pd(d);
}
In this case it makes sense to use a reference type, since you don't ever want DAO::m_d to be null, and its lifetime is controlled externally (from the main function in this case).
I use references in function arguments not just to avoid copies but also instead of pointers to avoid having to deal with NULL pointers where appropriate. Pointers model a "maybe there's a value, but maybe not (NULL)", references are a clear statement that a value is required.
... and to make it absolutely clear (-> comments). I tend to avoid pointers to model "maybe there are several values" - a vector is a better option here. Pointers to several values often end up in C-style programming because you usually have to pass the # of elements as well separately.
Use a const reference to give a name to a value, e.g.:
const Vec3 &ba=b-a;
This names the value, but doesn't necessarily create a variable for it. In theory, this gives the compiler more leeway and may allow it to avoid some copy constructor calls.
(Related non-duplicated Stack Overflow question at Const reference to temporary. The Herb Sutter link there has more information about this.)
The argument to the copy-constructor MUST be passed as a reference, since otherwise the copy constructor would need to call it self in an endless recursion (stack overflow).
I tend to agree, but perhaps const return values.
Well you kind of have two choices for aliasing other values(ignoring shared_ptrs and the like): pointers and references.
References must be initialized at construction to refer to something else. So semantically a reference can never be NULL. In reality, though, the underlying data can go away, giving you problems often more difficult to debug than if a pointer went away. So I'm not sure there's a real advantage here unless you were disciplined and consistent with how they were used vis-a-vis referring to items that were dynamically allocated. If you did this with pointers too, you'd avoid the same problems.
Perhaps more importantly, references can be used without thinking about all the issues that arise with pointers. This is probably the main advantage. Semantically a reference is the thing. If you guarantee as the caller/callee that the underlying memory doesn't go away, you don't have to confuse the user with any of the questions that come along with pointers (Do I need to free this? Could this be NULL? etc) and can safely use a reference for convenience.
An example of this might be a function that looks up the corresponding string for an enum,
const std::string& ConvertToString( someEnum val)
{
static std::vector< std::string > lookupTable;
if (lookupTable.empty())
{
// fill in lookup table
}
// ignoring the cast that would need to happen
return lookupTable[val]
}
Here the contract between the caller and the callee guarantees that the return type will always be there. You can safely return a reference, and avoid some of the questions that pointers invite.
References make code prettier. So use them whenever it takes a reference to beautify your code.
i would like to enlist some cases:
1) while writing singleton classes
class singleton
{
singleton();
explicit singleton(const singleton&);
singleton& operator=(const singleton&);
public:
static singleton& instance()
{
static singleton inst;
return inst;
}
};// this is called the 'Meyers' singleton pattern. refer to More Effective C++ by Scott Meyers
it has all the benefits, but avoids using the new operator
**2)**here is no such thing as a null reference. A reference must always refer to some object. As a result, if you have a variable whose purpose is to refer to another object, but it is possible that there might not be an object to refer to, you should make the variable a pointer, because then you can set it to null. On the other hand, if the variable must always refer to an object, i.e., if your design does not allow for the possibility that the variable is null, you should probably make the variable a reference
**3)**Because a reference must refer to an object, C++ requires that references be initialized:
string& rs; // error! References must
// be initialized
string s("xyzzy");
string& rs = s; // okay, rs refers to s
Pointers are subject to no such restriction
The fact that there is no such thing as a null reference implies that it can be more efficient to use references than to use pointers. That's because there's no need to test the validity of a reference before using it
**4)**Another important difference between pointers and references is that pointers may be reassigned to refer to different objects. A reference, however, always refers to the object with which it is initialized: ¤ Item M1, P10
string s1("Nancy");
string s2("Clancy");
string& rs = s1; // rs refers to s1
string *ps = &s1; // ps points to s1
rs = s2; // rs still refers to s1,
// but s1's value is now
// "Clancy"
ps = &s2; // ps now points to s2;
// s1 is unchanged
Stream operators are an obvious example
std::ostream & operator<< (std::ostream &, MyClass const &...) {
....
}
mystream << myClassVariable;
You obviously don't want a pointer as checking for NULL makes using an operator very tedious i.s.o. convenient
I've used a reference to an ostream instead of a pointer. I supppose that I prefer references to pointers when the class has a lot of operators.
What are some ways you can shoot yourself in the foot when using boost::shared_ptr? In other words, what pitfalls do I have to avoid when I use boost::shared_ptr?
Cyclic references: a shared_ptr<> to something that has a shared_ptr<> to the original object. You can use weak_ptr<> to break this cycle, of course.
I add the following as an example of what I am talking about in the comments.
class node : public enable_shared_from_this<node> {
public :
void set_parent(shared_ptr<node> parent) { parent_ = parent; }
void add_child(shared_ptr<node> child) {
children_.push_back(child);
child->set_parent(shared_from_this());
}
void frob() {
do_frob();
if (parent_) parent_->frob();
}
private :
void do_frob();
shared_ptr<node> parent_;
vector< shared_ptr<node> > children_;
};
In this example, you have a tree of nodes, each of which holds a pointer to its parent. The frob() member function, for whatever reason, ripples upwards through the tree. (This is not entirely outlandish; some GUI frameworks work this way).
The problem is that, if you lose reference to the topmost node, then the topmost node still holds strong references to its children, and all its children also hold a strong reference to their parents. This means that there are circular references keeping all the instances from cleaning themselves up, while there is no way of actually reaching the tree from the code, this memory leaks.
class node : public enable_shared_from_this<node> {
public :
void set_parent(shared_ptr<node> parent) { parent_ = parent; }
void add_child(shared_ptr<node> child) {
children_.push_back(child);
child->set_parent(shared_from_this());
}
void frob() {
do_frob();
shared_ptr<node> parent = parent_.lock(); // Note: parent_.lock()
if (parent) parent->frob();
}
private :
void do_frob();
weak_ptr<node> parent_; // Note: now a weak_ptr<>
vector< shared_ptr<node> > children_;
};
Here, the parent node has been replaced by a weak pointer. It no longer has a say in the lifetime of the node to which it refers. Thus, if the topmost node goes out of scope as in the previous example, then while it holds strong references to its children, its children don't hold strong references to their parents. Thus there are no strong references to the object, and it cleans itself up. In turn, this causes the children to lose their one strong reference, which causes them to clean up, and so on. In short, this wont leak. And just by strategically replacing a shared_ptr<> with a weak_ptr<>.
Note: The above applies equally to std::shared_ptr<> and std::weak_ptr<> as it does to boost::shared_ptr<> and boost::weak_ptr<>.
Creating multiple unrelated shared_ptr's to the same object:
#include <stdio.h>
#include "boost/shared_ptr.hpp"
class foo
{
public:
foo() { printf( "foo()\n"); }
~foo() { printf( "~foo()\n"); }
};
typedef boost::shared_ptr<foo> pFoo_t;
void doSomething( pFoo_t p)
{
printf( "doing something...\n");
}
void doSomethingElse( pFoo_t p)
{
printf( "doing something else...\n");
}
int main() {
foo* pFoo = new foo;
doSomething( pFoo_t( pFoo));
doSomethingElse( pFoo_t( pFoo));
return 0;
}
Constructing an anonymous temporary shared pointer, for instance inside the arguments to a function call:
f(shared_ptr<Foo>(new Foo()), g());
This is because it is permissible for the new Foo() to be executed, then g() called, and g() to throw an exception, without the shared_ptr ever being set up, so the shared_ptr does not have a chance to clean up the Foo object.
Be careful making two pointers to the same object.
boost::shared_ptr<Base> b( new Derived() );
{
boost::shared_ptr<Derived> d( b.get() );
} // d goes out of scope here, deletes pointer
b->doSomething(); // crashes
instead use this
boost::shared_ptr<Base> b( new Derived() );
{
boost::shared_ptr<Derived> d =
boost::dynamic_pointer_cast<Derived,Base>( b );
} // d goes out of scope here, refcount--
b->doSomething(); // no crash
Also, any classes holding shared_ptrs should define copy constructors and assignment operators.
Don't try to use shared_from_this() in the constructor--it won't work. Instead create a static method to create the class and have it return a shared_ptr.
I've passed references to shared_ptrs without trouble. Just make sure it's copied before it's saved (i.e., no references as class members).
Here are two things to avoid:
Calling the get() function to get the raw pointer and use it after the pointed-to object goes out of scope.
Passing a reference of or a raw pointer to a shared_ptr should be dangerous too, since it won't increment the internal count which helps keep the object alive.
We debug several weeks strange behavior.
The reason was:
we passed 'this' to some thread workers instead of 'shared_from_this'.
Not precisely a footgun, but certainly a source of frustration until you wrap your head around how to do it the C++0x way: most of the predicates you know and love from <functional> don't play nicely with shared_ptr. Happily, std::tr1::mem_fn works with objects, pointers and shared_ptrs, replacing std::mem_fun, but if you want to use std::negate, std::not1, std::plus or any of those old friends with shared_ptr, be prepared to get cozy with std::tr1::bind and probably argument placeholders as well. In practice this is actually a lot more generic, since now you basically end up using bind for every function object adaptor, but it does take some getting used to if you're already familiar with the STL's convenience functions.
This DDJ article touches on the subject, with lots of example code. I also blogged about it a few years ago when I first had to figure out how to do it.
Using shared_ptr for really small objects (like char short) could be an overhead if you have a lot of small objects on heap but they are not really "shared". boost::shared_ptr allocates 16 bytes for every new reference count it creates on g++ 4.4.3 and VS2008 with Boost 1.42. std::tr1::shared_ptr allocates 20 bytes. Now if you have a million distinct shared_ptr<char> that means 20 million bytes of your memory are gone in holding just count=1. Not to mention the indirection costs and memory fragmentation. Try with the following on your favorite platform.
void * operator new (size_t size) {
std::cout << "size = " << size << std::endl;
void *ptr = malloc(size);
if(!ptr) throw std::bad_alloc();
return ptr;
}
void operator delete (void *p) {
free(p);
}
Giving out a shared_ptr< T > to this inside a class definition is also dangerous.
Use enabled_shared_from_this instead.
See the following post here
You need to be careful when you use shared_ptr in multithread code. It's then relatively easy to become into a case when couple of shared_ptrs, pointing to the same memory, is used by different threads.
The popular widespread use of shared_ptr will almost inevitably cause unwanted and unseen memory occupation.
Cyclic references are a well known cause and some of them can be indirect and difficult to spot especially in complex code that is worked on by more than one programmer; a programmer may decide than one object needs a reference to another as a quick fix and doesn't have time to examine all the code to see if he is closing a cycle. This hazard is hugely underestimated.
Less well understood is the problem of unreleased references. If an object is shared out to many shared_ptrs then it will not be destroyed until every one of them is zeroed or goes out of scope. It is very easy to overlook one of these references and end up with objects lurking unseen in memory that you thought you had finished with.
Although strictly speaking these are not memory leaks (it will all be released before the program exits) they are just as harmful and harder to detect.
These problems are the consequences of expedient false declarations: 1. Declaring what you really want to be single ownership as shared_ptr. scoped_ptr would be correct but then any other reference to that object will have to be a raw pointer, which could be left dangling. 2. Declaring what you really want to be a passive observing reference as shared_ptr. weak_ptr would be correct but then you have the hassle of converting it to share_ptr every time you want to use it.
I suspect that your project is a fine example of the kind of trouble that this practice can get you into.
If you have a memory intensive application you really need single ownership so that your design can explicitly control object lifetimes.
With single ownership opObject=NULL; will definitely delete the object and it will do it now.
With shared ownership spObject=NULL; ........who knows?......
If you have a registry of the shared objects (a list of all active instances, for example), the objects will never be freed. Solution: as in the case of circular dependency structures (see Kaz Dragon's answer), use weak_ptr as appropriate.
Smart pointers are not for everything, and raw pointers cannot be eliminated
Probably the worst danger is that since shared_ptr is a useful tool, people will start to put it every where. Since plain pointers can be misused, the same people will hunt raw pointers and try to replace them with strings, containers or smart pointers even when it makes no sense. Legitimate uses of raw pointers will become suspect. There will be a pointer police.
This is not only probably the worst danger, it may be the only serious danger. All the worst abuses of shared_ptr will be the direct consequence of the idea that smart pointers are superior to raw pointer (whatever that means), and that putting smart pointers everywhere will make C++ programming "safer".
Of course the mere fact that a smart pointer needs to be converted to a raw pointer to be used refutes this claim of the smart pointer cult, but the fact that the raw pointer access is "implicit" in operator*, operator-> (or explicit in get()), but not implicit in an implicit conversion, is enough to give the impression that this is not really a conversion, and that the raw pointer produced by this non-conversion is an harmless temporary.
C++ cannot be made a "safe language", and no useful subset of C++ is "safe"
Of course the pursuit of a safe subset ("safe" in the strict sense of "memory safe", as LISP, Haskell, Java...) of C++ is doomed to be endless and unsatisfying, as the safe subset of C++ is tiny and almost useless, as unsafe primitives are the rule rather than the exception. Strict memory safety in C++ would mean no pointers and only references with automatic storage class. But in a language where the programmer is trusted by definition, some people will insist on using some (in principle) idiot-proof "smart pointer", even where there is no other advantage over raw pointers that one specific way to screw the program state is avoided.