I've found out that unique_ptr can point to an already existing object.
For example, I can do this :
class Foo {
public:
Foo(int nb) : nb_(nb) {}
private:
int nb_;
};
int main() {
Foo f1(2);
Foo* ptr1(&f1);
unique_ptr<Foo> s_ptr1(&f1);
return 0;
}
My question is :
If I create a class with unique_ptr< Bar > as data members (where Bar is a class where the copy constructor was deleted) and a constructor that takes pointers as argument, can I prevent the user from passing an already existing object/variable as an argument (in that constructor) (i.e. force him to use the new keyword) ?
Because if he does, I won't be able to guarantee a valide state of my class objects (the user could still modify data members with their address from outside of the class) .. and I can't copy the content of Bar to another memory area.
Example :
class Bar {
public:
Bar(/* arguments */) { /* data members allocation */ }
Bar(Bar const& b) = delete;
/* Other member functions */
private:
/* data members */
};
class Bar_Ptr {
public:
Bar_Ptr(Bar* ptr) {
if (ptr != nullptr) { ptr_ = unique_ptr<Bar> (ptr); }
} /* The user can still pass the address of an already existing Bar ... */
/* Other member functions */
private:
unique_ptr<Bar> ptr_;
};
You can't prevent programmers from doing stupid things. Both std::unique_ptr and std::shared_ptr contain the option to create an instance with an existing ptr. I've even seen cases where a custom deleter is passed in order to prevent deletion. (Shared ptr is more elegant for those cases)
So if you have a pointer, you have to know the ownership of it. This is why I prefer to use std::unique_ptr, std::shared_ptr and std::weak_ptr for the 'owning' pointers, while the raw pointers represent non-owning pointers. If you propagate this to the location where the object is created, most static analyzers can tell you that you have made a mistake.
Therefore, I would rewrite the class Bar_ptr to something like:
class Bar_ptr {
public:
explicit Bar_ptr(std::unique_ptr<Bar> &&bar)
: ptr(std::move(bar)) {}
// ...
}
With this, the API of your class enforces the ownership transfer and it is up to the caller to provide a valid unique_ptr. In other words, you shouldn't worry about passing a pointer which isn't allocated.
No one prevents the caller from writing:
Bar bar{};
Bar_ptr barPtr{std::unique_ptr<Bar>{&bar}};
Though if you have a decent static analyzer or even just a code review I would expect this code from being rejected.
No you can't. You can't stop people from doing stupid stuff. Declare a templated function that returns a new object based on the templated parameter.
I've seen something similar before.
The trick is that you create a function (let's call it make_unique) that takes the object (not pointer, the object, so maybe with an implicit constructor, it can "take" the class constructor arguments) and this function will create and return the unique_ptr. Something like this:
template <class T> std::unique_ptr<T> make_unique(T b);
By the way, you can recommend people to use this function, but no one will force them doing what you recommend...
You cannot stop people from doing the wrong thing. But you can encourage them to do the right thing. Or at least, if they do the wrong thing, make it more obvious.
For example, with Bar, don't let the constructor take naked pointers. Make it take unique_ptrs, either by value or by &&. That way, you force the caller to create those unique_ptrs. You're just moving them into your member variables.
That way, if the caller does the wrong thing, the error is in the caller's code, not yours.
Related
I'm fairly new to Pass By Reference, and I HAVE to make sure I understand this correctly. I have to convert all my Heap memory to Stack memory because my professor said so, and I'm stuck on two concepts.
What is the best way to store a reference in a class? I originally had member objects as non pointers, but noticed the deconstructor would be called on the member variable when the object (not member object) was popped off the stack. This makes me think it was a copy, and not actually a reference.
Here is an example of what I had originally:
class B
{
public:
B();
~B();
};
class A
{
private:
B b;
public:
A();
~A();
setB(B& bVar);
};
void A::setB(B& bVar)
{
b = bVar;
}
My solution was to change it to a pointer so it didn't call the deconstructor, but I'M NOT SURE IF THIS IS THE CORRECT WAY TO DO IT. Here was my solution:
class B
{
public:
B();
~B();
};
class A
{
private:
B* b;
public:
A();
~A();
setB(B& bVar);
};
void A::setB(B& bVar)
{
b = &bVar;
}
My second question is kind of related. I'm not sure what exactly happens when you have:
object1 = object2&.
Is object1 a copy or is it actually another identifier for object2?
References behave like symbolic aliases to instances, and are in some respects like "pointers" that can't (shouldn't) be null. For the sake of this explanation, I'll refer to them below as though they were pointers.
When you have a T&, it means that it is pointing to a T, and is not itself a copy.
When you have a T = T&, it means you'll get a copy (or a copy of a copy) depending on how the constructor or assignment operator are defined.
When you have an R& = L, it means you'll get copy of L into whatever the R& is pointing to (provided the assignment operator of R permits this).
Concerning the "correct" way of storing references, I would ask at least these questions:
Is it acceptable for the member reference to remain the same throughout the containing object's lifetime?
Will instances of the containing type always be destroyed before the object(s) pointed to by the member reference?
If both are true, then simply declaring and appropriately initializing a member T& should suffice:
class B
{
// details...
};
class A
{
B &_b;
public:
A(B &b) :
_b(b)
{}
};
Otherwise, despite the requirements imposed upon you, the situation might call for something like shared_ptr<> or similar.
References to objects living on the stack, in-turn held by other objects that themselves may be constructed in such a way that they will outlive their reference's lifespan are merely pointers waiting to dangle.
Consider copying, or arguing that heap-allocated memory is the better option.
If you are uncertain of the reference network induced by your program, you need to redesign it.
EDIT:
It is important to note that, when passing a reference to a function (const T& in particular), there are certain situations in which it can be elided by the compiler. For example: When such a function is inlined, references can be replaced by more efficient addressing logic than if they were required to be pointers.
In this respect, they are not pointers.
Suppose I have a class called foo which inherits from a class called bar.
I have a std::unique_ptr to an instance of foo and I want to pass it to a function that only takes std::unique_ptr<bar>. How can I convert the pointer so it works in my function?
You can convert a std::unique_ptr<foo> rvalue to an std::unique_ptr<bar>:
std::unique_ptr<foo> f(new foo);
std::unique_ptr<bar> b(std::move(f));
Obviously, the pointer will be owned by b and if b gets destroyed bar needs to have a virtual destructor.
Nothing special is required because of the inheritance. You need to use std::move to pass the unique_ptr to a function, but this is true even if the types match:
#include <memory>
struct A {
};
struct B : A {
};
static void f(std::unique_ptr<A>)
{
}
int main(int,char**)
{
std::unique_ptr<B> b_ptr(new B);
f(std::move(b_ptr));
}
You may use this syntax:
std::unique_ptr<parent> parentptr = std::unique_ptr<child>(childptr);
Or you may use std::move.
The other option is to emit raw pointer, but you need to change a function:
void func(const parent* ptr)
{
// actions...
}
func(*childptr);
Here is a good article about smart pointers and passing it to functions: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters.
You can't, because it would violate the most basic unique_ptr rule: there has to be only one instance that holds a given pointer, and the unique_ptr has full ownership of it (when it goes out of scope, the pointee is deleted).
unique_ptr<T> and unique_ptr<U> (where U : T) aren't compatible, as you've seen.
For shared_ptr, for which you can have multiple instances, there is std::static_pointer_cast that behaves just like a static_cast, except that it accepts a shared_ptr and returns another one (and both point to the same object).
If you absolutely need to use a unique_ptr, you'll have to create a function that first disowns your current unique_ptr and puts that pointer into a new one of the right type. You might also need to do the opposite conversion after your function call.
I'd like to know is it better to specify a default initialization for a smart-pointer or do a NULL value check before accessing the smart-pointers methods?
Currently I've been using the method below to avoid calling increment() on a NULL pointer. Is this a reasonable way of doing things or is there a pitfall that I don't see?
Note: We use a custom smart-pointer class and I don't have the Boost libraries on my current configuration to test compile this code. This should compile, but YMMV.
Example.h
#include <boost/shared_ptr.hpp>
class Foo
{
public:
Foo() : mFoo(0) {}
Foo(int rawValue) : mFoo(rawValue) {}
void increment() { mFoo++; }
private:
int mFoo;
};
typedef boost::shared_ptr<Foo> FooSP;
class MyClass
{
public:
MyClass() : mFoo(new Foo()) {}
FooSP foo() { return mFoo; }
void setFoo(FooSP newFoo) { mFoo = newFoo; }
private:
FooSP mFoo;
};
Main.cpp
#include <Example.h>
int main()
{
MyClass temp; // Default-constructed
temp.foo()->increment(); // Increment Foo's member integer
// Before: mFoo = 0
// After: mFoo = 1
FooSP tempFoo = new Foo(10); // Create a Foo with a default size
temp.setFoo(FooSP(new Foo(10))); // Explicitly set the FooSP member
temp.foo()->increment(); // Increment the new FooSP
// Before: mFoo = 10
// After: mFoo = 11
return 0;
}
If you are using a smart pointer as a general replacement for a pointer type, you cannot get away from a check for null. This is because a class defined with a smart pointer with a default constructor is likely to allow the smart pointer to be created with its default constructor. Dynamically creating a new object just to fill the pointer until you can set it seems to be a waste of resources.
shared_ptr's constructor is explicit, so your initialization of tempFoo won't compile. If you wanted to save a line of code, you can avoid declaring the temporary like this:
temp.setFoo(FooSP(new Foo(10)));
You can also declare the method of setFoo to take a constant reference, to avoid manipulating the reference count when taking in the parameter.
void setFoo(const FooSP &newFoo) { mFoo = newFoo; }
Or use swap on the parameter instance.
void setFoo(FooSP newFoo) { std::swap(mFoo, newFoo); }
If I were required to implement something along the lines of what you are proposing, I would create a static instance of Foo to serve as the null version, and then have the increment method throw an exception if it was the null version.
class Foo
{
public:
static Foo Null;
//...
void increment() {
if (this == &Null) throw Null;
mFoo++;
}
//...
};
struct DeleteFoo {
void operator () (Foo *t) const {
if (t != &Foo::Null) delete t;
}
};
class MyClass
{
public:
MyClass() : mFoo(&Foo::Null, DeleteFoo()) {}
//...
};
Note the custom deleter for FooSP to properly deal with Foo::Null.
is it better to specify a default initialization for a smart-pointer or do a NULL value check before accessing the smart-pointers methods?
There is no right answer which applies to every case (more soon). If I had to err to one or the other, I would err toward NULL testing without default initialization because that's an obvious programmer error which can be detected and corrected easily.
However, I think the right answer is that there are good reasons we use multiple idioms for construction and initialization, and that you should choose the best approach for your program.
Typically, I will be explicit (no default or no default initialization) in the lower level classes, as well as complex higher level classes. When the classes are mid-level and defaults and ownership are more obvious (often because of limited use cases), then a default may be sensible.
Often, you will just want to be consistent, to avoid surprising clients. You'll also need to be aware of the complexity of allocating default-initialized objects. If it's big and complex to create, and a default does not make sense, then you are simply wasting a lot of resources when the default-constructed object is the wrong choice.
a) do not apply a default where it does not make sense. the default should be obvious.
b) avoid wasted allocations.
In addition to the approaches you have mentioned, there are a few other angles you might also consider:
Matching Foo's declared constructors in MyClass. At least, the ones which pertain to MyClass.
If copyable and efficient to copy, passing a Foo to MyClass's constructor.
Passing Foo in a container (smart pointer in this case) to MyClass's constructor to remove any ambiguity and to offer the client the option to construct (and share, in the case of a shared pointer) Foo as they desire.
Is this a reasonable way of doing things or is there a pitfall that I don't see?
Wasted allocations. Surprising results. It can restrict capabilities. The most obvious, broadly applicable problems are time and resource consumption.
To illustrate some scenarios:
say Foo reads a 1MB file every time it is constructed. when construction parameters are necessary and the default is not the right option, the file would have to be read a second time. the innocent default would double the disk io required.
in another case, an omitted construction parameter may be another large or complex shared pointer. if absent, Foo may create its own -- when the resource could/should have been shared.
Constructors parameters are often very important, and often should not be erased from the interface. It's certainly fine to do so in some cases, but these conveniences can introduce a lot of restrictions or introduce much unnecessary allocations and CPU time as the contained object's complexity increases.
Using both approaches in your programs is fine. Using additional approaches I outlined is also fine. Specifically, using the right approach for the problem is ideal - there are multiple ways to implement ideal solutions available; you just have to determine what that is in the context of what it is your program is trying to do. All these approaches have separate pros and cons - there is often an ideal match for the context of your program's operation and exposed interfaces.
I want to gain a better understanding of how to implement the RAII idiom with my classes, through an example: What the recommended method is for ensuring pointers are free()'d properly in my class?
I have a class which should exist for the duration of the program. In the spirit of RAII and because I need to pass a reference to this class to other classes, I am holding it in a shared_ptr (not sure it actually needs to be held in a shared_ptr, but for fun, it is).
In the class ctor, I use 2 buffers (pointers) and then loop multiple times malloc()'ing, using the buffer and then free()'ing. The dtor should contain failsafe code to free the buffers, in the event of mishap.
The only way the dtor can see the buffers is if I declare them as class variables, however they are only used in the class ctor.
Example:
class Input
{
private:
PSOMETYPE buffer1;
public:
Input();
~Input();
}
Input::Input() : buffer1(NULL)
{
for(blahblah)
{
buffer1 = (PSOMETYPE)malloc(sizeof(SOMETYPE));
// Do work w/buffer1
if(buffer1 != NULL) { free(buffer1); buffer1 = NULL }
}
}
Input::~Input()
{
if(buffer1 != NULL) { free(buffer1); buffer1 = NULL }
}
Considering I only use the buffer in the ctor, does it make sense to declare it as a private class variable? If I declare it in the scope of the ctor, the dtor will have no knowledge as to what it is to free.
I know this is a trivial example, and honestly I could implement this as easily forgetting about using a smart pointer to reference my class and having a blank dtor, just free()'ing as I'm doing inside the loop. I have no mentor or schooling, and I'm uncertain of when the RAII idiom should be followed.
The spirit of RAII would be to use a local object to manage the locally allocated object, rather than artificially tying its lifetime to the object being constructed:
class Input
{
// no pointer at all, if it's only needed in the constructor
public:
Input();
// no explicit destructor, since there's nothing to explicitly destroy
};
Input::Input()
{
for(blahblah)
{
std::unique_ptr<SOMETYPE> buffer1(new SOMETYPE);
// or, unless SOMETYPE is huge, create a local object instead:
SOMETYPE buffer1;
// Do work w/buffer1
} // memory released automatically here
}
You should only ever have to use delete (or free, or whatever) yourself if you're writing a class whose purpose is to manage that resource - and usually there's already a standard class (such as a smart pointer or a container) that does what you want.
When you do need to write your own management class, always remember the Rule of Three: if your destructor deletes something, then the default copying behaviour of the class will almost certainly cause a double delete, so you need to declare a copy constructor and copy-assignment operator to prevent that. For example, with your class I could write the following incorrect code:
{
Input i1; // allocates a buffer, holds a pointer to it
Input i2(i1); // copies the pointer to the same buffer
} // BOOM! destroys both objects, freeing the buffer twice
The simplest way to prevent this is to delete the copy operations, so code like that will fail to compile:
class Input {
Input(Input const&) = delete; // no copy constructor
void operator=(Input) = delete; // no copy assignment
};
Older compilers may not support = delete; in which case you can get almost the same effect by declare them privately without = delete, and not implementing them.
I am new here.
I am also new on C++
So here is the class and function i wrote.But i got the compiler error
My class:
class fooPlayer
{
public:
void fooPlayerfunc(){}//doing something here
char askYesNo(std::string question);
};
class fooPlayerFactory
{
public:
virtual std::auto_ptr<fooPlayer> MakePlayerX() const;
virtual std::auto_ptr<fooPlayer> MakePlayerO() const;
private:
std::auto_ptr<fooPlayer> MakePlayer(char letter) const;
std::auto_ptr<fooPlayer> my_player;
};
Implement my class:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerX() const
{
char go_first = my_player->askYesNo("Do you require the first move?");
MakePlayer(go_first);
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerO() const
{
return my_player;
}
My main() function here:
int main()
{
fooPlayerFactory factory;
factory.MakePlayerX();
factory.MakePlayerO();
}
I got the error:
error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
I do not know how to change it even after reading the document on this link:
The reason for the error is that you are calling the copy constructor of auto_ptr my_player in fooPlayerFactory::MakePlayerO() which is a const method. That means that is cannot modify its members.
However the copy constructor of auto_ptr DOES modify the right hand side so returning my_player trys to change its pointer to 0 (NULL), while assigning the original pointer to the auto_ptr in the return value.
The signature of the copy constuctor is
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
not
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
The copy constructor of auto_ptr assigns ownership of the pointer to the left hand side, the right hand side then holds nothing.
I don't think you want to use auto_ptr here, you probably want boost::smart_ptr
It looks like you have mixed up two uses for auto_ptr
The first is as poor man's boost::scoped_ptr. This is to manage a single instance of a pointer in a class, the class manages the life time of the pointer. In this case you don't normally return this pointer outside your class (you can it is legal, but boost::smart_ptr / boost::weak_ptr would be better so clients can participate the life time of the pointer)
The second is its main purpose which is to return a newly created pointer to the caller of a function in an exception safe way.
eg
auto_ptr<T> foo() {
return new T;
}
void bar() {
auto_ptr<T> t = foo();
}
As I said I think you have mixed these two uses auto_ptr is a subtle beast you should read the auto_ptr docs carefully. It is also covered very well in Effective STL by Scott Meyers.
In your code:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
This is a const function, but fooPlayerfunc is not const - my compiler reports this error rather than the one you say you are getting. Are you posting the real code?
I don't think you actually want to constructing dynamic objects here.
A factory object creates and returns an object it normally does not keep a reference to it after creation (unless you are sharing it), and I don't actually see anywhere that you are creating the player.
If you only ever create one player internally in your (fooPlayerFactory). Then create an object and return references to it.
Edit: in response to the comment (which is correct, my bad), I left only the advice part.
Best practice is to have the factory methods just return a plain old pointer to the underlying object, and let the caller decide how to manage ownership (auto_ptr, scoped_ptr, or whatever).
Also your code is buggy, any class that implements virtual methods should have a virtual destructor.
I'm not seeing anywhere you construct my_player, so I have a feeling that some of the code is missing. Specifically, I think your constructor has this line:
my_player = new fooPlayer()
A fooPlayer object is not quite the same thing as an auto_ptr<fooPlayer> object, and auto_ptr is intentionally designed to prevent assigning from one to the other because, frankly, the alternative is worse. For the details, look up (1) conversion constructors, (2) the explicit keyword, and (3) copy constructors and destructive copy semantics.
You should change the constructor to either:
class fooPlayerFactory {
public:
fooPlayerFactory()
{
my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
}
Or (using a member initializer list):
class fooPlayerFactory {
public:
fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new fooPlayer()) { }
The solution isn't pretty but, like I said, the alternative is worse due to some really arcane details.
As a bit of advice, though, you're making life harder than it needs to be; and may in fact be causing strange bugs. auto_ptr exists to manage the lifetime of an object, but the only reason you need to worry about the lifetime of my_player is that you've allocated it with new. But there's no need to call new, and in fact there's no need to keep my_player. And unless fooPlayerFactory is meant to be the base class for some other factory, there's no need to mark functions virtual.
Originally I thought you could get away with simply returning copies of the my_player object, but there's a problem: before returning my_player from MakePlayer() you call a method on it, and I assume that method changes the internal state of my_player. Further calls to MakePlayer() will change the state again, and I think you're going to eventually have my_player in the wrong state. Instead, return a different fooPlayer object with each request. Don't do memory management, just promise to construct the object. That way the user can decide on memory allocation:
fooPlayerFaclotry factory;
fooPlayer on_stack = factory.MakePlayerX();
fooPlayer* on_heap_raw_pointer = new fooPlayer(factory.MakePlayerO());
std::auto_ptr<fooPlayer> on_heap_managed_scope
= std::auto_ptr<fooPlayer>(factory.MakePlayerX());
I would change fooPlayerFactory to look like this:
class fooPlayerFactory
{
private:
fooPlayer MakePlayer(const char letter) const
{
fooPlayer result;
result.fooPlayerfunc();
return result;
}
public:
fooPlayer* MakePlayerX() const
{
char go_first = askYesNo("Do you require the first move?");
return MakePlayer(go_first);
}
fooPlayer MakePlayerO() const
{
return fooPlayer();
}
};