I'm asking something that looks trivial but I had problems with. Let's assume, for the sake of explanation, a structure like this one:
class MyClass{
int* m_Number;
public:
int value() const {return *m_Number;}
void setValue(int val){*m_Number=val;}
MyClass() : m_Number(new int(3)){}
~MyClass() {if(m_Number) delete m_Number;}
MyClass(const MyClass& other):m_Number(new int(*other.m_Number)){}
MyClass& operator=(const MyClass& other){if(m_Number) *m_Number=*other.m_Number; else m_Number=new int(*other.m_Number); return *this;}
MyClass& operator=(MyClass&& other){std::swap(m_Number,other.m_Number); return *this;}
MyClass(MyClass&& other){
//????
}
}
What should I put in there?
My options are:
1)
MyClass(MyClass&& other)
:m_Number(other.m_Number)
{
other.m_Number=nullptr;
}
But then the moved from object is not in a valid state. calling value() should return something valid but undetermined while here I just segfault. I could check m_Number in value() and setValue() but you realise it's a huge drag in real code.
2)
MyClass(MyClass&& other)
:m_Number(other.m_Number)
{
other.m_Number= new int(3);
}
But a move constructor that can throw is a no go (or at least as I understand it) and it's also a drag of the performance enhancement, in fact this code is equal or worse that the copy constructor.
What do you think?
Did I miss something?
Is there a preferred way to go?
Thanks in advance
Edit: This question received an answer from the convener of the std committee and it fundamentally disagrees with the answers to this post. You can find it in this article https://herbsutter.com/2020/02/17/move-simply/
Firstly, there's no reason to use new and delete here, you should be using make_unique<int> to create the object and a unique_ptr<int> to manage it automatically. But that doesn't solve your problem, of what the move constructor can do. There are some other options in addition to the two you suggest:
3) don't give it a move constructor, just leave it as copyable
4) document that calling value or setValue on a moved-from object is not allowed, and leave the moved-from object with a null pointer. Depending where moves happen in your program that might be fine. If moved-from objects are never accessed, everything just works.
4a) As above, but add sanity checks in case it does ever happen:
int value() const {
assert(m_Number != nullptr);
return *m_Number;
}
or:
int value() const {
if (m_Number == nullptr)
throw std::logic_error("accessed a moved-from object");
return *m_Number;
}
5) Add checks to setValue to re-initialize the object with a new int if it's currently null, and make value return some default value:
int value() const { return m_Number ? *m_Number : 0; }
void setValue(int val) {
if (!m_Number)
m_Number = new int(val);
else
*m_Number = val;
}
You are dereferencing your pointer in the .value() call. You will always segfault in the event that m_Number is invalid.
Your first solution to the move constructor is correct, you should set the 'other' object to a default state. To solve this, you could make your .value() method throw, or return a default value in the event of non-existent resource.
Your destructor already accounts for the null case, so make sure the rest of it accounts for it as well.
Your first approach is probably the best if modifying MyClass such that m_Number = nullptr is a valid state is reasonable to do (and would be best practice if it were the default state too). I'd argue if having no-heap memory associated with MyClass is not a valid state, you should be allocating it inside of a std::unique_ptr, and passing around a raw pointer to that instead of implementing a move constructor.
If 1. is not an option, this is a reasonable way to go. While there certainly is a performance hit for allocating un-needed memory, it is quite minor, especially considering you are constructing a class as part of this operation (which itself requires memory). If its a small chunk of memory that is needed as in your example, the memory allocator will likely draw it from its own pool without the need of a system call. If it is a large chunk of memory (as I would expect since you're implementing move semantics), then on most modern operating systems it will be a lazy allocation (so it would still be better than a copy constructor).
Do not use raw owning pointers, convert your class to use std::unique_ptr, and all your problems will go away.
Related
As mentioned here you can use reference (d-reference) instead of pointer (d-pointer) in case of PIMPL idiom.
I'm trying to understand if there are any serious issues with this implementation and what are the pros and cons.
Pros:
Shorter syntax because of usage of "." instead of "->".
...
Cons:
What if the new ObjectPivate() fails and new doesn't throw (e.g.: new(std::nothrow) or custom new) and returns nullptr instead? You need to implement additional stuff to check if the referance is valid. In case of pointer you just use:
if (m_Private)
m_Private->Foo();
In rare case of multiple constructors for the Object with complex initialisation logic the solution could be not applicable. [© JamesKanze]
It fills more natural to use pointer for memory management. [© JamesKanze]
Some additional implementation details needs to be considered (use of swap()) to ensure the exception-safety (e.g. implementation of assignment operator) [© Matt Yang]
...
Here the sample code for illustration:
// Header file
class ObjectPrivate;
class Object
{
public:
Object();
virtual ~Object();
virtual void Foo();
private:
ObjectPrivate& m_Private;
};
// Cpp file
class ObjectPrivate
{
public:
void Boo() { std::cout << "boo" << std::endl; }
};
Object::Object() :
m_Private(* new ObjectPrivate())
{
}
Object::~Object()
{
delete &m_Private;
}
void Object::Foo()
{
m_Private.Boo();
}
It's really just a matter of style. I tend to not use
references in classes to begin with, so using a pointer in the
compilation firewall just seems more natural. But there's
usually no real advantage one way or the other: the new can
only fail by means of an exception.
The one case where you might favor the pointer is when the
object has a lot of different constructors, some of which need
preliminary calculations before calling the new. In this
case, you can initialize the pointer with NULL, and then call
a common initialization routine. I think such cases are rare,
however. (I've encountered it once, that I can recall.)
EDIT:
Just another style consideration: a lot of people don't like something like delete &something;, which is needed if you use references rather than pointers. Again, it just seems more natural (to me, at least), that objects managing memory use pointers.
It's not convenient to write exception-safe code I think.
The first version of Object::operator=(Object const&) might be:
Object& operator=(Object const& other)
{
ObjectPrivate *p = &m_Private;
m_Private = other.m_Private; // Dangerous sometimes
delete *p;
}
It's dangerous if ObjectPrivate::operator=(ObjectPrivate const&) throws exception. Then what about using a temporary variable? Aha, no way. operator=() has to be invoked if you want change m_Private.
So, void ObjectPrivate::swap(ObjectPrivate&) noexcept can act as our savior.
Object& operator=(Object const& other)
{
ObjectPrivate *tmp = new ObjectPrivate(other.m_Private);
m_Private.swap(*tmp); // Well, no exception.
delete tmp;
}
Then consider the implementation of void ObjectPrivate::swap(ObjectPrivate&) noexcept. Let's assume that ObjectPrivate might contain a class instance without swap() noexcept or operator=() noexcept. I think it's hard.
Alright then, this assumption is too strict and not correct sometimes. Even so, it's not necessary for ObjectPrivate to provide swap() noexcept in most cases, because it's usually a helper structure to centralize data.
By contrast, pointer can save a lot of brain cells.
Object& operator=(Object const& other)
{
ObjectPrivate *tmp = new ObjectPrivate(*other.p_Private);
delete p_Private;
p_Private = tmp; // noexcept ensured
}
It's much more elegant if smart pointers are used.
Object& operator=(Object const& other)
{
p_Private.reset(new ObjectPrivate(*other.p_Private));
}
Some quick and obvious additions:
Pro
The reference must not be 0.
The reference may not be assigned another instance.
Class responsibilities/implementation are simpler due to fewer variables.
The compiler could make some optimizations.
Con
The reference may not be assigned another instance.
The reference will be too restrictive for some cases.
The most interesting C++ question I've encountered recently goes as follows:
We determined (through profiling) that our algorithm spends a lot of time in debug mode in MS Visual Studio 2005 with functions of the following type:
MyClass f(void)
{
MyClass retval;
// some computation to populate retval
return retval;
}
As most of you probably know, the return here calls a copy constructor to pass out a copy of retval and then the destructor on retval. (Note: the reason release mode is very fast for this is because of the return value optimization. However, we want to turn this off when we debug so that we can step in and nicely see things in the debugger IDE.)
So, one of our guys came up with a cool (if slightly flawed) solution to this, which is, create a conversion operator:
MyClass::MyClass(MyClass *t)
{
// construct "*this" by transferring the contents of *t to *this
// the code goes something like this
this->m_dataPtr = t->m_dataPtr;
// then clear the pointer in *t so that its destruction still works
// but becomes 'trivial'
t->m_dataPtr = 0;
}
and also changing the function above to:
MyClass f(void)
{
MyClass retval;
// some computation to populate retval
// note the ampersand here which calls the conversion operator just defined
return &retval;
}
Now, before you cringe (which I am doing as I write this), let me explain the rationale. The idea is to create a conversion operator that basically does a "transfer of contents" to the newly constructed variable. The savings happens because we're no longer doing a deep copy, but simply transferring the memory by its pointer. The code goes from a 10 minute debug time to a 30 second debug time, which, as you can imagine, has a huge positive impact on productivity. Granted, the return value optimization does a better job in release mode, but at the cost of not being able to step in and watch our variables.
Of course, most of you will say "but this is abuse of a conversion operator, you shouldn't be doing this kind of stuff" and I completely agree. Here's an example why you shouldn't be doing it too (this actually happened:)
void BigFunction(void)
{
MyClass *SomeInstance = new MyClass;
// populate SomeInstance somehow
g(SomeInstance);
// some code that uses SomeInstance later
...
}
where g is defined as:
void g(MyClass &m)
{
// irrelevant what happens here.
}
Now this happened accidentally, i.e., the person who called g() should not have passed in a pointer when a reference was expected. However, there was no compiler warning (of course). The compiler knew exactly how to convert, and it did so. The problem is that the call to g() will (because we've passed it a MyClass * when it was expecting a MyClass &) called the conversion operator, which is bad, because it set the internal pointer in SomeInstance to 0, and rendered SomeInstance useless for the code that occured after the call to g(). ... and time consuming debugging ensued.
So, my question is, how do we gain this speedup in debug mode (which has as direct debugging time benefit) with clean code that doesn't open the possibility to make such other terrible errors slip through the cracks?
I'm also going to sweeten the pot on this one and offer my first bounty on this one once it becomes eligible. (50 pts)
You need to use something called "swaptimization".
MyClass f(void)
{
MyClass retval;
// some computation to populate retval
return retval;
}
int main() {
MyClass ret;
f().swap(ret);
}
This will prevent a copy and keep the code clean in all modes.
You can also try the same trick as auto_ptr, but that's more than a little iffy.
If your definition of g is written the same as in your code base I'm not sure how it compiled since the compiler isn't allowed to bind unnamed temporaries to non-const references. This may be a bug in VS2005.
If you make the converting constructor explicit then you can use it in your function(s) (you would have to say return MyClass(&retval);) but it won't be allowed to be called in your example unless the conversion was explicitly called out.
Alternately move to a C++11 compiler and use full move semantics.
(Do note that the actual optimization used is Named Return Value Optimization or NRVO).
The problem is occuring because you're using MyClass* as a magic device, sometimes but not always. Solution: use a different magic device.
class MyClass;
class TempClass { //all private except destructor, no accidental copies by callees
friend MyClass;
stuff* m_dataPtr; //unfortunately requires duplicate data
//can't really be tricked due to circular dependancies.
TempClass() : m_dataPtr(NULL) {}
TempClass(stuff* p) : m_dataPtr(p) {}
TempClass(const TempClass& p) : m_dataPtr(p) {}
public:
~TempClass() {delete m_dataPtr;}
};
class MyClass {
stuff* m_dataPtr;
MyClass(const MyClass& b) {
m_dataPtr = new stuff();
}
MyClass(TempClass& b) {
m_dataPtr = b.m_dataPtr ;
b.m_dataPtr = NULL;
}
~MyClass() {delete m_dataPtr;}
//be sure to overload operator= too.
TempClass f(void) //note: returns hack. But it's safe
{
MyClass retval;
// some computation to populate retval
return retval;
}
operator TempClass() {
TempClass r(m_dataPtr);
m_dataPtr = nullptr;
return r;
}
Since TempClass is almost all private (friending MyClass), other objects cannot create, or copy TempClass. This means the hack can only be created by your special functions when clearly told to, preventing accidental usage. Also, since this doesn't use pointers, memory can't be accidentally leaked.
Move semantics have been mentioned, you've agreed to look them up for education, so that's good. Here's a trick they use.
There's a function template std::move which turns an lvalue into an rvalue reference, that is to say it gives "permission" to move from an object[*]. I believe you can imitate this for your class, although I won't make it a free function:
struct MyClass;
struct MovableMyClass {
MyClass *ptr;
MovableMyClass(MyClass *ptr) : ptr(ptr) {}
};
struct MyClass {
MyClass(const MovableMyClass &tc) {
// unfortunate, we need const reference to bind to temporary
MovableMyClass &t = const_cast<MovableMyClass &>(tc);
this->m_dataPtr = t.ptr->m_dataPtr;
t.ptr->m_dataPtr = 0;
}
MovableMyClass move() {
return MovableMyClass(this);
}
};
MyClass f(void)
{
MyClass retval;
return retval.move();
}
I haven't tested this, but something along those lines. Note the possibility of doing something const-unsafe with a MovableMyClass object that actually is const, but it should be easier to avoid ever creating one of those than it is to avoid creating a MyClass* (which you've found out is quite difficult!)
[*] Actually I'm pretty sure I've over-simplified that to the point of being wrong, it's actually about affecting what overload gets chosen rather than "turning" anything into anything else as such. But causing a move instead of a copy is what std::move is for.
A different approach, given your special scenario:
Change MyClass f(void) (or operator+) to something like the following:
MyClass f(void)
{
MyClass c;
inner_f(c);
return c;
}
And let inner_f(c) hold the actual logic:
#ifdef TESTING
# pragma optimize("", off)
#endif
inline void inner_f(MyClass& c)
{
// actual logic here, setting c to whatever needed
}
#ifdef TESTING
# pragma optimize("", on)
#endif
Then, create an additional build configurations for this kind of testing, in which TESTING is included in the preprocessor definitions.
This way, you can still take advantage of RVO in f(), but the actual logic will not be optimized on your testing build. Note that the testing build can either be a release build or a debug build with optimizations turned on. Either way, the sensitive parts of the code will not be optimized (you can use the #pragma optimize in other places too, of course - in the code above it only affects inner_f itself, and not code called from it).
Possible solutions
Set higher optimization options for the compiler so it optimizes out the copy construction
Use heap allocation and return pointers or pointer wrappers, preferably with garbage collection
Use the move semantics introduced in C++11; rvalue references, std::move, move constructors
Use some swap trickery, either in the copy constructor or the way DeadMG did, but I don't recommend them with a good conscience. An inappropriate copy constructor like that could cause problems, and the latter is a bit ugly and needs easily destructible default objects which might not be true for all cases.
+1: Check and optimize your copy constructors, if they take so long then something isn't right about them.
I would prefer to simply pass the object by reference to the calling function when MyClass is too big to copy:
void f(MyClass &retval) // <--- no worries !
{
// some computation to populate retval
}
Just simple KISS principle.
Okay I think I have a solution to bypass the Return Value Optimization in release mode, but it depends on the compiler and not guaranteed to work. It is based on this.
MyClass f (void)
{
MyClass retval;
MyClass dummy;
// ...
volatile bool b = true;
if b ? retval : dummy;
}
As for why the copy construction takes so long in DEBUG mode, I have no idea. The only possible way to speed it up while remaining in DEBUG mode is to use rvalue references and move semantics. You already discovered move semantics with your "move" constructor that accepts pointer. C++11 gives a proper syntax for this kind of move semantics. Example:
// Suppose MyClass has a pointer to something that would be expensive to clone.
// With move construction we simply move this pointer to the new object.
MyClass (MyClass&& obj) :
ptr (obj.ptr)
{
// We set the source object to some trivial state so it is easy to delete.
obj.ptr = NULL;
}
MyClass& operator = (MyClass&& obj) :
{
// Here we simply swap the pointer so the old object will be destroyed instead of the temporary.
std::swap(ptr, obj.ptr);
return *this;
}
I'm getting a segmentation fault which I believe is caused by the copy constructor. However, I can't find an example like this one anywhere online. I've read about shallow copy and deep copy but I'm not sure which category this copy would fall under. Anyone know?
MyObject::MyObject{
lots of things including const and structs, but no pointers
}
MyObject::MyObject( const MyObject& oCopy){
*this = oCopy;//is this deep or shallow?
}
const MyObject& MyObject::operator=(const MyObject& oRhs){
if( this != oRhs ){
members = oRhs.members;
.....//there is a lot of members
}
return *this;
}
MyObject::~MyObject(){
//there is nothing here
}
Code:
const MyObject * mpoOriginal;//this gets initialized in the constructor
int Main(){
mpoOriginal = new MyObject();
return DoSomething();
}
bool DoSomething(){
MyObject *poCopied = new MyObject(*mpoOriginal);//the copy
//lots of stuff going on
delete poCopied;//this causes the crash - can't step into using GDB
return true;
}
EDIT: Added operator= and constructor
SOLVED: Barking up the wrong tree, it ended up being a function calling delete twice on the same object
It is generally a bad idea to use the assignment operator like this in the copy constructor. This will default-construct all the members and then assign over them. It is much better to either just rely on the implicitly-generated copy constructor, or use the member initializer list to copy those members that need copying, and apply the appropriate initialization to the others.
Without details of the class members, it is hard to judge what is causing your segfault.
According to your code you're not creating the original object... you're just creating a pointer like this:
const MyObject * mpoOriginal;
So the copy is using bad data into the created new object...
Wow....
MyObject::MyObject( const MyObject& oCopy)
{
*this = oCopy;//is this deep or shallow?
}
It is neither. It is a call to the assignment operator.
Since you have not finished the construction of the object this is probably ill-advised (though perfectly valid). It is more traditional to define the assignment operator in terms of the copy constructor though (see copy and swap idium).
const MyObject& MyObject::operator=(const MyObject& oRhs)
{
if( this != oRhs ){
members = oRhs.members;
.....//there is a lot of members
}
return *this;
}
Basically fine, though normally the result of assignment is not cont.
But if you do it this way you need to divide up your processing a bit to make it exception safe. It should look more like this:
const MyObject& MyObject::operator=(const MyObject& oRhs)
{
if( this == oRhs )
{
return *this;
}
// Stage 1:
// Copy all members of oRhs that can throw during copy into temporaries.
// That way if they do throw you have not destroyed this obbject.
// Stage 2:
// Copy anything that can **not** throw from oRhs into this object
// Use swap on the temporaries to copy them into the object in an exception sage mannor.
// Stage 3:
// Free any resources.
return *this;
}
Of course there is a simpler way of doing this using copy and swap idum:
MyObject& MyObject::operator=(MyObject oRhs) // use pass by value to get copy
{
this.swap(oRhs);
return *this;
}
void MyObject::swap(MyObject& oRhs) throws()
{
// Call swap on each member.
return *this;
}
If there is nothing to do in the destructor don't declare it (unless it needs to be virtual).
MyObject::~MyObject(){
//there is nothing here
}
Here you are declaring a pointer (not an object) so the constructor is not called (as pointers don;t have constructors).
const MyObject * mpoOriginal;//this gets initialized in the constructor
Here you are calling new to create the object.
Are you sure you want to do this? A dynamically allocated object must be destroyed; ostensibly via delete, but more usually in C++ you wrap pointers inside a smart pointer to make sure the owner correctly and automatically destroys the object.
int main()
{ //^^^^ Note main() has a lower case m
mpoOriginal = new MyObject();
return DoSomething();
}
But since you probably don't want a dynamic object. What you want is automatic object that is destroyed when it goes out of scope. Also you probably should not be using a global variable (pass it as a parameter otherwise your code is working using the side affects that are associated with global state).
int main()
{
const MyObject mpoOriginal;
return DoSomething(mpoOriginal);
}
You do not need to call new to make a copy just create an object (passing the object you want to copy).
bool DoSomething(MyObject const& data)
{
MyObject poCopied (data); //the copy
//lots of stuff going on
// No need to delete.
// delete poCopied;//this causes the crash - can't step into using GDB
// When it goes out of scope it is auto destroyed (as it is automatic).
return true;
}
What you are doing is making your copy constructor use the assignment operator (which you don't seem to have defined). Frankly I'm surprised it compiles, but because you haven't shown all your code maybe it does.
Write you copy constructor in the normal way, and then see if you still get the same problem. If it's true what you say about 'lots of things ... but I don't see any pointers' then you should not be writing a copy constructor at all. Try just deleting it.
I don't have a direct answer as for what exactly causes the segfault, but conventional wisdom here is to follow the rule of three, i.e. when you find yourself needing any of copy constructor, assignment operator, or a destructor, you better implement all three of them (c++0x adds move semantics, which makes it "rule of four"?).
Then, it's usually the other way around - the copy assignment operator is implemented in terms of copy constructor - copy and swap idiom.
MyObject::MyObject{
lots of things including const and structs, but no pointers
}
The difference between a shallow copy and a deep copy is only meaningful if there is a pointer to dynamic memory. If any of those member structs isn't doing a deep copy of it's pointer, then you'll have to work around that (how depends on the struct). However, if all members either don't contain pointers, or correctly do deep copies of their pointers, then the copy constructor/assignment is not the source of your problems.
It's either, depending on what your operator= does. That's where the magic happens; the copy constructor is merely invoking it.
If you didn't define an operator= yourself, then the compiler synthesised one for you, and it is performing a shallow copy.
Say, i have a function which returns a reference and i want to make sure that the caller only gets it as a reference and should not receive it as a copy.
Is this possible in C++?
In order to be more clear. I have a class like this.
class A
{
private:
std::vector<int> m_value;
A(A& a){ m_value = a.m_value; }
public:
A() {}
std::vector<int>& get_value() { return m_value; }
};
int main()
{
A a;
std::vector<int> x = a.get_value();
x.push_back(-1);
std::vector<int>& y = a.get_value();
std::cout << y.size();
return 0;
}
Thanks,
Gokul.
You can do what you want for your own classes by making the class non copyable.
You can make an class non copyable by putting the copy constructor and operator= as private or protected members.
class C
{
private:
C(const C& other);
const C& operator=(const C&);
};
There is a good example of making a NonCopyable class here that you can derive from for your own types.
If you are using boost you can also use boost::noncopyable.
Alt solution:
Another solution is to have a void return type and make the caller pass their variable by reference. That way no copy will be made as you're getting a reference to the caller's object.
If your function returns a reference to an object that shouldn't have been copied, then your function already has done what it could do to prevent copying. If someone else calls your function and copies the return value, then either
it's an error the caller made, because the object should never be copied (in which case the return type probably shouldn't have been copyable in the first place), or
it's irrelevant for the caller because the function is only called once in a week (in which case you must not try to cripple your callers' code), or
it's a pretty dumb oversight on the side of the caller (in which case the error will be found by profiling).
For #1, either you return have your own type or you can wrap whatever your return in your own type. Note that the only difference between #2 and #3 is the relevance - and if it's relevant, profiling will find it.
IMO you should not cripple your code by returning a pointer when what you need is a reference. Experienced programmers, seeing the pointer, will immediately ask whether they need to check for a NULL return value, whether the object is allocated dynamically and, if so, who is responsible for cleaning it up.
You should also not blindly forbid copying of whatever you return, if you cannot eliminate the possibility that copying is needed.
In the end it's the old motto, which C++ inherited from C: Trust your users to know what they are doing.
It "depends". Yes, you can hide the copy-constructor (and assignment operator), and your object becomes noncopyable:
struct foo
{
private:
foo(const foo&); // dont define
foo& operator=(const foo&); // dont define
}:
But if you're wondering about one specific function (i.e., normally copyable, but not for this function), no. In fact, what can you do about the caller anyway?
const foo& f = get_foo(); // okay, by reference, but...
foo f2 = foo(foo(foo(foo(foo(foo(f)))))); // :[
If your caller wants to do something, there isn't much you can do to stop it.
In C++11, you can prevent the copy constructor from being called by deleting it:
class A{
public:
A(const A&) = delete;
}
Are you trying to prevent a common typo that causes large objects to accidentally be copied? If so, you could return by pointer instead. Leaving off an & is pretty easy, but it takes a little bit of effort to copy an object from a pointer. OTOH, the resulting code will be uglier, so it's up to you whether it's worth it.
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();
}
};