What is the C++ equivalent of Objective C "#property (nonatomic, retain)"? - c++

I am am wondering how to create properly properties in C++. In Objective C, I use "#property" (in general with the (nonatomic, retain) attributes).
What is the proper way in C++ ?
Thanks !!

As Seva said, there are no properties in that kind of sense in C++. What you could do: write a class with a boost::share_ptr member variable, and optionally write getter and setter for that member. But that isn't even really necessary, although maybe deemed good behaviour.
typedef boost::shared_ptr<std::string> StringPtrT;
class A {
public:
void setStringProperty(StringPtrT s) { this->string_property = s; }
StringPtrT getStringProperty() const { return this->string_property; }
protected:
StringPtrT string_property;
}
The shared pointer will deal with the sharing and reference counting, basically simulating some kind of "retain" behaviour. IIRC boost shared_ptr types are always atomic, when it comes to updateing the reference counts. However, access to the object itself (de-referencing the pointer) will be non-atomic. You will have to deal with that yourself, if needed.

#Ame's code is correct, but there's no particular requirement to use shared_ptr here. I am very torn on the use of shared_ptr broadly. It can be useful, but introduces a lot of subtle complexity in my experience. It is not the traditional C++ approach. C++ often prefers strong object ownership rather than shared ownership (which is the common model in ObjC). If you do use shared_ptr, it's built-in for Cocoa platforms, so you don't need boost. You may want to read Wrapping C++ – Take 2, Part 2 to get a sense of some of the complexities around shared_ptr (it's a little dated, and some of it is not applicable to ARC code).
That said, #Ame's approach is essentially correct. But you typically would use copying for simple properties rather than shared_ptr. (This is particularly true for strings, which you also copy in most ObjC code.) For someone looking for a style guide, I typically recommend Google's. It's not perfect, but it's very well considered, and it's good to start with something that at least is known to work for a lot of people before inventing your own. (EDIT: See #Matthieu M.'s comment below for a dissenting opinion.)
class MyClass {
public:
...
int num_entries() const { return num_entries_; }
void set_num_entries(int num_entries) { num_entries_ = num_entries; }
private:
int num_entries_;
};
Note the private: is correct here. I disagree with #Ame's use of protected:. Just like ObjC, you should use accessors even inside of classes, and definitely you should use them in subclasses. Allowing subclasses to directly access ivars is fragile. It requires subclasses to have special knowledge of their superclass.
For string properties and other simple or immutable objects, you should generally use the copy constructor rather than anything like shared_ptr. For more complex, mutable objects, C++ typically encourages strong object ownership rather than shared ownership. So there should (in general) be some one object responsible for creating, managing, and destroying that other complex object. Everyone else should just get references from the object's owner. They should never create or destroy the object themselves.
It's not that shared or strict ownership is better IMO. It's just that shared ownership is the ObjC way and all code works that way (and it is extremely elegant in that). Strict ownership is more the C++ way (as much as C++ can be said to have "a way") and trying to shoehorn shared ownership into it is often fragile.

Related

Is using pointers in C++ always bad?

I was told to avoid using pointers in C++. It seems that I can't avoid them however in the code i'm trying to write, or perhaps i'm missing out on other great C++ features.
I wish to create a class (class1) which contains another class (class2) as a data member. I then want class2 to know about class1 and be able to communicate with it.
I could have a reference to class1 as a member in class2 but that then means I need to provide a reference to class1 as a parameter in the constructor of class2 and use initialiser lists which I don't want. I'm trying to do this without needing the constructor to do it.
I would like for class2 to have a member function called Initialise which could take in the reference to class1, but this seems impossible without using pointers. What would people recommend here? Thanks in advance.
The code is completely simplified just to get the main idea across :
class class1
{
public:
InitialiseClass2()
{
c2.Initialise(this);
}
private:
class2 c2;
};
class class2
{
public:
Initialise(class1* c1)
{
this->c1 = c1;
}
private:
class1* c1;
};
this seems impossible without using pointers
That is incorrect. Indeed, to handle a reference to some other object, take a reference into a constructor:
class class2
{
public:
class2(class1& c1)
: c1(c1)
{}
private:
class1& c1;
};
The key here is to initialise, not assign, the reference. Whether this is possible depends on whether you can get rid of your Initialise function and settle into RAII (please do!). After that, whether this is actually a good idea depends on your use case; nowadays, you can almost certainly make ownership and lifetime semantics much clearer by using one of the smart-pointer types instead — even if it's just a std::weak_ptr.
Anyway, speaking more generally.
Are pointers "always" bad? No, of course not. I'd almost be tempted to say that managing dynamic memory yourself is "always" bad, but I won't make a generalisation.
Should you avoid them? Yes.
The difference is that the latter is a guideline to steer you away from manual memory management, and the former is an attempted prohibition.
No, using pointers in C++ is not bad at all, and I see this anti-advice over and over again. What is bad is managing pointers by yourself, unless you are creating a pointer-managing low-level entity.
Again, I shall make a very clear distinction. Using pointers is good. Very few real C++ programs can do without USING pointers. Managing pointers is bad, unless you are working on pointer manager.
A pointer can be nullptr whereas a reference must always be bound to something (and cannot be subsequently re-bound to something else).
That's the chief distinction and the primary consideration for your design choice.
Memory management of pointers can be delegated to std::shared_ptr and std::unique_ptr as appropriate.
well, I never had the need to 2 classes to have reciprocal reference and for good reasons, how do you know how to test those classes? If later you need to change something in the way the 2 classes communicates you will probably have to change code in both classes). You can workaround in many ways:
You may need in reality just 1 class ( you have broken into much classes)
You can register a Observer for a class (using a 3rd class, in that case you will end up with a pointer, but at least the 2 classes are less coupled and it is easier test them).
You can think (maybe) to a new interface that require only 1 class to call methods on the other class
You could pass a lambda (or a functor if you do not have C++11) into one of the methods of the class removing the need to a back reference
You could pass a reference of the class inside a method.
Maybe you have to few classes and in reality you need a third class than communicates with both classes.
It is possible you need a Visitor (maybe you really need multiple dispatch)
Some of the workarounds above need pointers, some not. To you the choice ;)
NOTE: However what you are doing is perfectly fine to me (I see you do some trickery only in constructors, but probably you have more omitted code, in wich case that can cause troubles to you). In my case I "register" one class into another, then after the constructor called I have only one class calling the other and not viceversa.
First of all whenever you have a circular dependency in your design think about it twice and make sure it's the way to go. Try to use the Dependency inversion principle in order to analyze and fix your dependencies.
I was told to avoid using pointers in C++. It seems that I can't avoid them however in the code i'm trying to write, or perhaps i'm missing out on other great C++ features.
Pointers are a powerful programming tool. Like any other feature in the C++ (or in any programming language in general) they have to be used when they are the right tool. In C++ additionally you have access to references which are similar to pointers in usage but with a better syntax. Additionally they can't be null. Thus they always reference a valid object.
So use pointers when you ever need to but try to avoid using raw pointers and prefer a smart pointer as alternative whenever possible. This will protect you against some trivial memory leak problems but you still have to pay attention to your object life-cycle and for each dynamically allocated object you should know clearly who create it and when/whom will release the memory allocated for the object.
Pointers (and references) are very useful in general because they could be used to pass parameters to a method by reference so you avoid passing heavy objects by value in the stack. Imagine the case for example that you have a very big array of heavy objects (which copy/= operator is time consuming) and you would like to sort these objects. One simple method is to use pointers to these objects so instead of moving the whole object during the sorting operation you just move the pointers which are very lightweight data type (size of machine address basically).

Best way to manage memory ownership in C++? Shared-pointers or other mechanisms?

In a new piece of code I have several different classes that refer to each other. Something like this (this is not my actual situation but an example of something similar):
class BookManager
{
...
};
class Book
{
public:
void setBookManager(BookManager *bookManager) {m_bookManager = bookManager;}
private:
BookManager *m_bookManager;
};
Every book refers to a book manager, but the problem is that many books will have its own specific BookManager, but some books may share a common BookManager.
The caller doesn't really specify what the Book should do with its BookManager, but in about 90% of the cases, the BookManager can be destroyed together with the Book. In about 10% of the cases, the same BookManager is reused for multiple books, and the BookManager must not be deleted with the Book.
Deleting the BookManager together with the Book is handy in those 90% of the cases, as the caller of Book::setBookManager doesn't need to remember the BookManager anymore. It just dies with the Book itself.
I see two alternative solutions for solving this.
First is to make extensive use of shared pointers. If the caller is not interested anymore in the BookManager afterwards, it doesn't keep a shared pointer to it. If it is still interested in it, or if it wants the BookManager to be shared over multiple books, it keeps the shared pointer and passes it to those multiple books.
A second alternative is to tell the Book explicitly what to do with the ownership of the book, like this:
class Book
{
public:
void setBookManager(BookManager *bookManager, book takeOwnership=true)
{
m_bookManager = bookManager;
m_hasOwnership = takeOwnership;
}
~Book()
{
if (m_hasOwnership && m_bookManager) delete m_bookManager;
}
private:
BookManager *m_bookManager;
bool m_hasOwnership;
};
The second solution seems much easier and allows us to use normal pointer syntax (BookManager * as opposed to std::shared_ptr<BookManager>), but it seems less 'clean' than the shared pointer approach.
Another alternative might be to have a typedef in BookManager like this:
class BookManager
{
public:
typedef std::shared_ptr<BookManager> Ptr;
...
};
Which allows us to write this:
BookManager::Ptr bookManager;
Which looks more like the the normal pointer-syntax than the original shared pointer syntax.
Does anyone have experience with either approach?
Any other suggestions?
In C++ if you have shared, un-coordinated access to common objects then the most common approach is some kind of reference counting, which you get from shared_ptr.
The only downside is that it isn't pervasive in C++ (especially libraries), so you sometimes need access to the raw pointer. In those cases, you need to be careful to keep the object alive.
I suggest that if you used shared_ptr -- try to use it everywhere, unless it's impossible. And yes, use the typedef if you want.
You seem to have this pretty well thought through. Looks like an ideal use for shared_ptr to me.
In the interests of adding SOME value for you, make sure you look at the templates for efficient shared_ptr creation here.
There are 2 kinds of "ownership" in C++:
deterministic ownership: at any moment you can point who is responsible for the resource
shared ownership: at any moment there might be several owners, they are hard to pinpoint though
shared_ptr, as the name implies, is for the second case. It is rarely required, especially with the introduction of move semantics and thus unique_ptr, but in those cases where it is actually required, it's invaluable.
Looking at your case, the question I have is: do you actually need shared ownership ?
One typical solution to avoid shared ownership is to use a Factory, which will be the sole owner of all the objects it creates, and guarantees they are alive as long the Factory itself is alive.
It might be "less safe" than using a shared_ptr, but there are very interesting arguments:
the lifetime of the objects is deterministic once more, much easier to debug
there is no risk of creating a cycle of references (and leaking memory) by accident
Unless you are memory constrained (in which case the sooner the objects get deleted the better it is), you might wish to take a BookManagerFactory approach here.
Only when you know exactly where the object is owned and take care to delete it there (!), should you use bare pointers. I have a "stack" of classes that each hold unique parent pointer, in which case the reference count would always be 1 and you can access the deepest element through the last child. It seems like you have a much more complicated setup here, though, go with smart pointers. Remember that even if a bare pointer might seem cleaner or easier, unique_ptr should be recommended, but you might have to battle move vs copy assignment in pre-conversion code and cryptic error messages resulting from the switch.
Lou Franco already gave you the answer, but as a side note: Your second implementation idea is essentially what an auto_ptr does (when take ownership is true).
A better solution might be to have the Book class hold a handle (e.g. array index or hash) to a BookManager that residese in some BookManagerCache class. The Cache class is solely responsible for managing the lifetimes of BookManagers.

Using reference as class members for dependencies

I am going back to C++ after spending some time in memory-managed languages, and I'm suddently kinda lost as to what is the best way to implement dependency injection. (I am completely sold to DI because I found it to be the simplest way to make test-driven design very easy).
Now, browsing SO and google got me quite a number of opinions on the matter, and I'm a bit confused.
As an answer to this question, Dependency injection in C++ , someone suggested that you should not pass raw pointers around, even for dependency injection. I understand it is related to ownership of the objects.
Now, ownership of objects is also tackled (although not into enough details to my state ;) ) in the infamous google style guide : http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Smart_Pointers
So what I understand is that in order to make it clearer which object has ownership of which other objects, you should avoid passing raw pointers around. In particular, it seems to be against this kind of coding :
class Addict {
// Something I depend on (hence, the Addict name. sorry.)
Dependency * dependency_;
public:
Addict(Dependency * dependency) : dependency_(dependency) {
}
~Addict() {
// Do NOT release dependency_, since it was injected and you don't own it !
}
void some_method() {
dependency_->do_something();
}
// ... whatever ...
};
If Dependency is a pure virtual class (aka poor-man's-Interface ), then this code makes it easy to inject a mock version of the Dependency (using something like google mock).
The problem is, I don't really see the troubles I can get in with this kind of code, and why I should want to use anything else than raw pointers ! Is it that it is not clear where the dependency comes from?
Also, I read quite a few posts hinting that one should really be using references in this situation, so is this kind of code better?
class Addict {
// Something I depend on (hence, the Addict name. sorry.)
const Dependency & dependency_;
public:
Addict(const Dependency & dependency) : dependency_(dependency) {
}
~Addict() {
// Do NOT release dependency_, since it was injected and you don't own it !
}
void some_method() {
dependency_.do_something();
}
// ... whatever ...
};
But then I get other, equally authoritive advices against using references as member: http://billharlan.com/pub/papers/Managing_Cpp_Objects.html
As you can see I am not exactly sure about the relative pros and cons of the various approaches, so I am a bit confused. I am sorry if this has been discussed to death, or if it is only a matter of personnal choice and consistency inside a given project ... but any idea is welcome.
Answers summary
(I don't know if it is good SO-tiquette to do this, but I'll add code example for what I gathered from answers...)
From the various responses, here's what I'll probably end up doing in my case:
pass dependencies as reference (at least to make sure NULL is not possible)
in the general case where copying is not possible, explicitly disallow it, and store dependencies as reference
in the rarer case where copying is possible, store dependencies as RAW pointers
let the creator of the dependencies (factory of some kind) decide between stack allocation or dynamic allocation (and in the latter case, management through a smart pointer)
establish a convention to separate dependencies from own resources
So I would end up with something like:
class NonCopyableAddict {
Dependency & dep_dependency_;
// Prevent copying
NonCopyableAddict & operator = (const NonCopyableAddict & other) {}
NonCopyableAddict(const NonCopyableAddict & other) {}
public:
NonCopyableAddict(Dependency & dependency) : dep_dependency_(dep_dependency) {
}
~NonCopyableAddict() {
// No risk to try and delete the reference to dep_dependency_ ;)
}
//...
void do_some_stuff() {
dep_dependency_.some_function();
}
};
And for a copyable class:
class CopyableAddict {
Dependency * dep_dependency_;
public:
// Prevent copying
CopyableAddict & operator = (const CopyableAddict & other) {
// Do whatever makes sense ... or let the default operator work ?
}
CopyableAddict(const CopyableAddict & other) {
// Do whatever makes sense ...
}
CopyableAddict(Dependency & dependency) : dep_dependency_(&dep_dependency) {
}
~CopyableAddict() {
// You might be tempted to delete the pointer, but its name starts with dep_,
// so by convention you know it is not your job
}
//...
void do_some_stuff() {
dep_dependency_->some_function();
}
};
From what I understood, there is no way to express the intent of "I have a pointer to some stuff, but I don't own it" that the compiler can enforce. So I'll have to resort to naming convention here...
Kept for reference
As pointed out by Martin, the following example does not solve the problem.
Or, assuming I have a copy constructor, something like:
class Addict {
Dependency dependency_;
public:
Addict(const Dependency & dependency) : dependency_(dependency) {
}
~Addict() {
// Do NOT release dependency_, since it was injected and you don't own it !
}
void some_method() {
dependency_.do_something();
}
// ... whatever ...
};
There is no hard and fast rule:
As people have mentioned using references inside objects can cause copy problems (and it does) so it is not a panacea, but for certain situation it can be useful (that is why C++ gives us the option to do it all these different ways). But using RAW pointers is really not an option. If you are dynamically allocating objects then you should always be maintaining them with smart pointers and your object should also be using smart pointers.
For people who demand examples: Streams are always passed and stored as references (as they can't be copied).
Some Comments on your code examples:
Example one and two
Your first example with pointers. Is basically the same as the second example using references. The difference being that a reference can not be NULL. When you pass a reference the object is already alive and thus should have a lifespan greater than the object you are testing already (If it was created on the stack) so it should be safe to keep a reference. If you are dynamically creating pointers as dependencies I would consider using boost::shared_pointer or std::auto_ptr depending if ownership of the dependency is shared or not.
Example Three:
I don't see any great use for your third example. This is because you can not use polymorphic types (If you pass an object derived from Dependency it will be sliced during the copy operation). Thus the code may as well be inside Addict rather than a separate class.
Bill Harlen: (http://billharlan.com/pub/papers/Managing%5FCpp%5FObjects.html)
Not to take anything away from Bill But:
I have never heard of him.
He is a Geo-Physists not a computer programmer
He recomends programming in Java to improve your C++
The languages are now so different in usage that is utterly false).
If you want to use references of What to-do/not to-do.
Then I would pick one of the Big names in the C++ field:
Stroustrup/Sutter/Alexandrescu/Meyers
Summary:
Don't use RAW pointers (when ownership is required)
Do use smart pointers.
Don't copy objects into your object (it will slice).
You can use references (but know the limitations).
My example of Dependency injection using references:
class Lexer
{
public: Lexer(std::istream& input,std::ostream& errors);
... STUFF
private:
std::istream& m_input;
std::ostream& m_errors;
};
class Parser
{
public: Parser(Lexer& lexer);
..... STUFF
private:
Lexer& m_lexer;
};
int main()
{
CLexer lexer(std::cin,std::cout); // CLexer derived from Lexer
CParser parser(lexer); // CParser derived from Parser
parser.parse();
}
// In test.cpp
int main()
{
std::stringstream testData("XXXXXX");
std::stringstream output;
XLexer lexer(testData,output);
XParser parser(lexer);
parser.parse();
}
Summary: If you need to store a reference, store a pointer as a private variable and access it through a method which dereferences it. You can stick a check that the pointer isn't null in the object's invariant.
In depth:
Firstly, storing references in classes makes it impossible to implement a sensible and legal copy constructor or assignment operator, so they should be avoided. It is usually a mistake to use one.
Secondly, the type of pointer/reference passed in to functions and constructors should indicate who has responsibility for freeing the object and how it should be freed:
std::auto_ptr - the called function is responsible for freeing, and will do so automatically when it's done. If you need copy semantics, the interface must provide a clone method which should return an auto_ptr.
std::shared_ptr - the called function is responsible for freeing, and will do so automatically when it's done and when all other references to the object are gone. If you need shallow copy semantics the compiler generated functions will be fine, if you need deep copying the interface must provide a clone method which should return a shared_ptr.
A reference - the caller has responsibility. You don't care - the object may be stack allocated for all you know. In this case you should pass by reference but store by pointer. If you need shallow copy semantics the compiler generated functions will be fine, if you need deep copying you're in trouble.
A raw pointer. Who knows? Could be allocated anywhere. Could be null. You might be responsible for freeing it, you might not.
Any other smart pointer - it should manage the lifetime for you, but you'll need to look at the documentation to see what the requirements are for copying.
Note that the methods which give you responsibility for freeing the object don't break DI - freeing the object is simply a part of the contract you have with the interface (as you don't need to know anything about the concrete type to free it).
I would steer clear of references as members since they tend to cause no end of headaches if you end up sticking one of your objects in an STL container. I would look into using a combination of boost::shared_ptr for ownership and boost::weak_ptr for dependents.
[update 1]
If you can always guarantee the dependency outlives the addict, you can use a raw pointer/reference, of course. between these two, I'd make a very simple decision: pointer if NULL is allowed, reference otherwise.
(The point of my original post was that neither pointer nor reference solve the lifetime problem)
I'd follow the infamous google style guideline here, and use smart pointers.
Both a pointer and a reference have the same problem: you need to make sure the dependency outlives the addict. That pushes a quite nasty responsibility onto the client.
With a (reference-counted) smart pointer, the policy becomes dependency is destroyed when noone uses it anymore. Sounds perfect to me.
Even better: with boost::shared_ptr (or a similar smart pointer that allows a type-neutral destruction policy) the policy is attached to the object at construction - which usually means everything affecting the dependency ends up in a single place.
The typical problems of smart pointers - overhead and circular references - rarely come into play here. Dependency instances usually aren't tiny and numerous, and a dependency that has a strong reference back to its addicts is at least a code smell. (still, you need to keep these things in mind. Welcome back to C++)
Warning: I am not "totally sold" to DI, but I'm totally sold on smart pointers ;)
[update 2]
Note that you can always create a shared_ptr to a stack/global instance using a null deleter.
This requires both sides to support this, though: addict must make guarantees that it will not transfer a reference to the dependency to someone else who might live longer, and caller is back with the responsibility ensuring lifetime. I am not to happy with this solution, but have used this on occasion.
But then I get other, equally authoritive advices against using references as member : http://billharlan.com/pub/papers/Managing%5FCpp%5FObjects.html
In this case I think you only want to set the object once, in the constructor, and never change it so no problem.
But if you want to change it later on, use an init function, have a copy constructor, in short everything that would have to change the reference you will have to use pointers.
It has been asked before, but my SO search skills are not up to finding it. To summarise my position - you should very rarely, if ever, use references as class members. Doing so causes all sorts of initialisation, assignment and copying problems. Instead, use a pointer or a value.
Edit: Found one - this is a question with a variety of opinions as answers: Should I prefer pointers or references in member data?
I can here my downmoderation coming already, but I will say that there should be no reference members in a class FOR ANY REASO, EVER. Except if they are a simple constant value. The reasons for this are many, the second you start this you open up all the bad things in C++. See my blog if you really care.

Is it wise to provide access to weak_ptr in a library interface?

I have written a library that exposes references to several related object types. All of these objects have their lifetimes managed by the library internally via boost::shared_ptr
A user of the library would also be able to know, by nature of the library, the lifetimes of any of the exposed objects. So they could store pointers or keep references to these objects. It would be reasonable for them to do this and know when those objects are no longer valid.
But I feel guilty forcing my users to be reasonable.
Is it acceptable to have a library expose weak_ptr's to its objects? Have other libraries done this?
I have profiled this library's usage in apps and have found it to be too mission-critical to expose weak_ptr exclusively.
Would it be wiser to have matching API functions expose either a reference or a weak_ptr or to make any object capable of exposing a weak_ptr to itself?
If the smart_ptrs are already directly accessible to the library's users, then they've already got access to the weak_ptrs, simply via the corresponding weak_ptr's constructor. But if the smart_ptrs are all internal to the library, that's a different story.
In that case, I'd recommend letting each object pass out weak_ptrs to itself, in addition to any other access your library offers. That gives the users the most flexibility: if they need a weak_ptr, they've got immediate access to it; if they need a shared_ptr, they can easily get it; and if they just need access to the object itself, they can ignore the smart pointers entirely.
Of course, I don't know what your library does or how it's used or designed. That might change my recommendation.
Coming up with convoluted mechanisms to get at the objects of your library will only result in people not using your library. If the semantics of the library dictate you need to have people using weak_ptrs, there no way around the user knowing that the objects may go away at some point. Make the interface express as much information about the usage of the library as possible, keeps documentation down and makes it infinitely easier to use.
You can't design around bad/inexperienced users.
If you give your clients access to weak_ptrs they can just lock them to create shared_ptrs and end up delaying the destruction of objects. That might cause problems with your library.
I suggest wrapping a weak_ptr in some other class and giving the caller a shared_ptr to that. That way they can't just call weak_ptr<T>::lock(). You seem to have performance constraints that might influence how you implement it, but a shared_ptr<InterfaceClass> might be a good way to go, and keep the class with the weak_ptr internal to your library.
That way you also keep these implementation details out of your library interface and you can change the way you implement it without changing your interface.
I don't see any problem with exposing weak_ptrs, especially given that TR1 has similar smart pointers (PDF).
TR1 is largely implemented by Visual Studio and GCC, but not some of the other compilers out there. But when it's implemented in all the compilers you care about, you may want to rework the API to expose those smart pointers instead.
If you want to both trap invalid use of the library (trying to access the objects when they have been deleted) as well as have a high-performance API (no weak_ptr's and shared_ptr's in the API), then you could consider have a different API for debug and nondebug builds.
Let's suppose for simplicity that you have only one class of objects you expose; call this class Object. The pointer type which you return from the API for accessing the internal objects is then defined as:
#ifdef DEBUG
typedef ObjectPtrFacade ObjectPtr
#else
typedef Object * ObjectPtr;
#endif
Here the facade is class which you write. It works roughly like this:
class ObjectPtrFacade {
public:
ObjectPtrFacade(Object *o) : wptr(o) { }
// copy constructor and assignment here etc. (not written)
Object * operator -> () const { return access(); }
Object & operator * () const { return *access(); }
private:
Object * access() {
assert(wptr.use_count() > 0);
return (Object *)(wptr.lock());
}
weak_ptr<Object> wptr;
}
In this way, whenever you build a debugging build, you have a special kind of smart pointer in use which asserts before accessing the object that its use_count() is higher than zero, i.e. that the object still exists. If the object has been released, you get a failing assert, which is better than a null pointer reference.
In general of course it is so that using weak_ptr's does not help if you have "stupid" users of the API, because they could call lock() and then still make a null-pointer reference after the weak_ptr returns a shared_ptr which is empty...

What is the best way to implement smart pointers in C++?

I've been evaluating various smart pointer implementations (wow, there are a LOT out there) and it seems to me that most of them can be categorized into two broad classifications:
1) This category uses inheritance on the objects referenced so that they have reference counts and usually up() and down() (or their equivalents) implemented. IE, to use the smart pointer, the objects you're pointing at must inherit from some class the ref implementation provides.
2) This category uses a secondary object to hold the reference counts. For example, instead of pointing the smart pointer right at an object, it actually points at this meta data object... Who has a reference count and up() and down() implementations (and who usually provides a mechanism for the pointer to get at the actual object being pointed to, so that the smart pointer can properly implement operator ->()).
Now, 1 has the downside that it forces all of the objects you'd like to reference count to inherit from a common ancestor, and this means that you cannot use this to reference count objects that you don't have control over the source code to.
2 has the problem that since the count is stored in another object, if you ever have a situation that a pointer to an existing reference counted object is being converted into a reference, you probably have a bug (I.E., since the count is not in the actual object, there is no way for the new reference to get the count... ref to ref copy construction or assignment is fine, because they can share the count object, but if you ever have to convert from a pointer, you're totally hosed)...
Now, as I understand it, boost::shared_pointer uses mechanism 2, or something like it... That said, I can't quite make up my mind which is worse! I have only ever used mechanism 1, in production code... Does anyone have experience with both styles? Or perhaps there is another way thats better than both of these?
"What is the best way to implement smart pointers in C++"
Don't! Use an existing, well tested smart pointer, such as boost::shared_ptr or std::tr1::shared_ptr (std::unique_ptr and std::shared_ptr with C++ 11)
If you have to, then remember to:
use safe-bool idiom
provide an operator->
provide the strong exception guarantee
document the exception requirements your class makes on the deleter
use copy-modify-swap where possible to implement the strong exception guarantee
document whether you handle multithreading correctly
write extensive unit tests
implement conversion-to-base in such a way that it will delete on the derived pointer type (policied smart pointers / dynamic deleter smart pointers)
support getting access to raw pointer
consider cost/benifit of providing weak pointers to break cycles
provide appropriate casting operators for your smart pointers
make your constructor templated to handle constructing base pointer from derived.
And don't forget anything I may have forgotten in the above incomplete list.
Just to supply a different view to the ubiquitous Boost answer (even though it is the right answer for many uses), take a look at Loki's implementation of smart pointers. For a discourse on the design philosophy, the original creator of Loki wrote the book Modern C++ Design.
I've been using boost::shared_ptr for several years now and while you are right about the downside (no assignment via pointer possible), I think it was definitely worth it because of the huge amount of pointer-related bugs it saved me from.
In my homebrew game engine I've replaced normal pointers with shared_ptr as much as possible. The performance hit this causes is actually not so bad if you are calling most functions by reference so that the compiler does not have to create too many temporary shared_ptr instances.
Boost also has an intrusive pointer (like solution 1), that doesn't require inheriting from anything. It does require changing the pointer to class to store the reference count and provide appropriate member functions. I've used this in cases where memory efficiency was important, and didn't want the overhead of another object for each shared pointer used.
Example:
class Event {
public:
typedef boost::intrusive_ptr<Event> Ptr;
void addRef();
unsigned release();
\\ ...
private:
unsigned fRefCount;
};
inline void Event::addRef()
{
fRefCount++;
}
inline unsigned Event::release(){
fRefCount--;
return fRefCount;
}
inline void intrusive_ptr_add_ref(Event* e)
{
e->addRef();
}
inline void intrusive_ptr_release(Event* e)
{
if (e->release() == 0)
delete e;
}
The Ptr typedef is used so that I can easily switcth between boost::shared_ptr<> and boost::intrusive_ptr<> without changing any client code
If you stick with the ones that are in the standard library you will be fine.
Though there are a few other types than the ones you specified.
Shared: Where the ownership is shared between multiple objects
Owned: Where one object owns the object but transfer is allowed.
Unmovable: Where one object owns the object and it can not be transferred.
The standard library has:
std::auto_ptr
Boost has a couple more than have been adapted by tr1 (next version of the standard)
std::tr1::shared_ptr
std::tr1::weak_ptr
And those still in boost (which in relatively is a must have anyway) that hopefully make it into tr2.
boost::scoped_ptr
boost::scoped_array
boost::shared_array
boost::intrusive_ptr
See:
Smart Pointers: Or who owns you baby?
It seems to me this question is kind of like asking "Which is the best sort algorithm?" There is no one answer, it depends on your circumstances.
For my own purposes, I'm using your type 1. I don't have access to the TR1 library. I do have complete control over all the classes I need to have shared pointers to. The additional memory and time efficiency of type 1 might be pretty slight, but memory usage and speed are big issues for my code, so type 1 was a slam dunk.
On the other hand, for anyone who can use TR1, I'd think the type 2 std::tr1::shared_ptr class would be a sensible default choice, to be used whenever there isn't some pressing reason not to use it.
The problem with 2 can be worked around. Boost offers boost::shared_from_this for this same reason. In practice, it's not a big problem.
But the reason they went with your option #2 is that it can be used in all cases. Relying on inheritance isn't always an option, and then you're left with a smart pointer you can't use for half your code.
I'd have to say #2 is best, simply because it can be used in any circumstances.
Our project uses smart pointers extensively. In the beginning there was uncertainty about which pointer to use, and so one of the main authors chose an intrusive pointer in his module and the other a non-intrusive version.
In general, the differences between the two pointer types were not significant. The only exception being that early versions of our non-intrusive pointer implicitly converted from a raw pointer and this can easily lead to memory problems if the pointers are used incorrectly:
void doSomething (NIPtr<int> const &);
void foo () {
NIPtr<int> i = new int;
int & j = *i;
doSomething (&j); // Ooops - owned by two pointers! :(
}
A while ago, some refactoring resulted in some parts of the code being merged, and so a choice had to be made about which pointer type to use. The non-intrusive pointer now had the converting constructor declared as explicit and so it was decided to go with the intrusive pointer to save on the amount of code change that was required.
To our great surprise one thing we did notice was that we had an immediate performance improvement by using the intrusive pointer. We did not put much research into this, and just assumed that the difference was the cost of maintaining the count object. It is possible that other implementations of non-intrusive shared pointer have solved this problem by now.
What you are talking about are intrusive and non-intrusive smart pointers. Boost has both. boost::intrusive_ptr calls a function to decrease and increase the reference count of your object, everytime it needs to change the reference count. It's not calling member functions, but free functions. So it allows managing objects without the need to change the definition of their types. And as you say, boost::shared_ptr is non-intrusive, your category 2.
I have an answer explaining intrusive_ptr: Making shared_ptr not use delete. In short, you use it if you have an object that has already reference counting, or need (as you explain) an object that is already referenced to be owned by an intrusive_ptr.