When making a curses version of Snake, I found that the this pointer was bindable for reconstruction from inside an 'update' method.
The issue with this is that, although very convenient (saves having to rebind 'player' in a game object), it doesn't feel particularly idiomatic.
Using the snake as an example, we'd be destroying it and reconstructing it as we're inside a method call on the initial(?) snake.
Here's an example of rebinding this in some struct A:
struct A
{
int first;
A(int first) : first(first){};
void method(int i);
};
void A::method(int i)
{
*this = i;
}
It's legal, but if I saw it I would question whether the author knew what they were doing: Did they really mean to invoke this->operator=()? Surely there's a better way to do... whatever it is they're trying to do.
In your case, *this = i is equivalent to this->operator=(i). Since there's no operator=(int) defined, it uses the default assignment operator and the A(int) constructor to perform this->operator=(A(i)). The net effect is exactly the same as if you had written:
this->first = i;
Why didn't they just assign to first directly? I'd be asking.
If for some reason you do want all those steps, I'd at least make the implicit A(int) construction explicit:
*this = A(i);
*this = i; implicitly constructs new instance of A as A::A(int) is not an explicit constructor and therefore creates the implicit conversion from int to A. *this = i; then calls default A::operator= with this new instance of A constructed from i. Then the new instance of A is destroyed.
So the code *this = i; is equivalent to operator=(A(i)); in your case.
It's legal to do so, but the code readability suffers from such a big amount of implicit actions.
You aren't destroying the object pointed to by this, you are calling it's operator=, which will copy first from a temporary initialised from i. You destroy the temporary after the assignment.
It might be clearer to write an A& operator=(int) which had the same effect.
Related
I have the following code snippet:
#include <iostream>
using namespace std;
class A {
int* data;
int size;
public:
A(int s):size(s)
{
data = new int[size];
}
A() {
data = nullptr;
}
~A() {
if (data) delete [] data;
}
};
class B {
A a[2];
public:
B() {
a[0] = A(10);
a[1] = A(11);
}
};
int main(int argc, char *argv[]) {
B b;
}
In the C++ code above, I have class A which has an array member int* data, and the (de)allocation of memory are handled by (de)constructor. The I created class B which has an array of class A of fixed length as a data member.
My question is: how to elegantly initialise the member A a[2]? In the code above, the A(10) and A(11) are created on the stack, when jumping out of the scope, their destructors will be called, hence the data comes invalid. When jumping of the main function's scope, the pointers held by a[2] will be deallocated twice, causing the error:
pointer being freed was not allocated.
One possible solution is to carefully design a copy constructor and a move constructor, by doing so the above coding paradigm could work.
Another solution I've tried is to initialise the array in the initialization list of class B:
B() : a { A(10), A(11) }
This solution works and I don't really tell the underlying mechanism of initialization list. I think it must be quite different from simply construct and copy. I really expected some experts could give an elaborate explanation of this mechanism. Of course, this solution is ugly hard-coded and not flexible.
So I wonder if there are some programming paradigms in C++ to tackle this design problem?
In the code above, the A(10) and A(11) are created on the stack
They are temporary objects. It is not specified where they are created or if they're created at all.
when jumping out of the scope, their destructors will be called
The destructor of each temporary will be called after the corresponding move assignment statement ends.
One possible solution is to carefully design a copy constructor and a move constructor, by doing so the above coding paradigm could work.
And {copy,move} assignment operator too. You should always do that when the implicitly declared ones don't do the right thing. And they never do the right thing if you delete something in the destructor.
Another solution I've tried is to initialise the array in the initialization list of class B
This solution works and I don't really tell the underlying mechanism of initialization list. I think it must be quite different from simply construct and copy.
The bug in the original code is badly behaving move assignment operator of A. Since the initialization list never move assigns from a temporary, it never triggers the bug.
This is actually the more elegant way to construct a that you asked for. Not because it avoids the bug, but because avoiding unnecessary moving is good thing, intrinsically.
So I wonder if there are some programming paradigms in C++ to tackle this design problem?
Yes. RAII and Single responsibility principle. Unless your class does nothing else, besides managing the memory pointed by data, it should not be managing the memory. Instead, it should delegate the memory management to a RAII object. In this case, you should use a std::vector member.
class A {
std::vector<int> data;
public:
A(int s):data(s) {}
A() = default;
};
Using an initializer list to construct B::a, like this:
class B {
A a[2];
public:
B() : a({10, 11}){
}
};
The ideal answer would be to force A to use movements instead of copies, or on a copy to allocate new space for the item. Of the two, the most efficient is the former and so I will expand on it below:
Forcing movement can be done in two fashions:
Delete the copy constructor and copy operator=, and implement your own move constructor and operator=
Consistently use std::move and std::swap.
Of these, the former is superior in that you will be unable to accidentally copy the class, but with the latter the fact that you are moving will be more evident.
To delete the default copy methods do:
class A {
A( const A& a ) = delete;
A& operator =( const A& a ) = delete;
}
I was reading C++11 Faq and came across this code. I have a better understanding of C++ coding, but I'm still not able to understand the below code.
template<class T>
class Handle {
T* p;
public:
Handle(T* pp) : p{pp} {}
~Handle() { delete p; } // user-defined destructor: no implicit copy or move
Handle(Handle&& h) :p{h.p} { h.p=nullptr; }; // transfer ownership
Handle& operator=(Handle&& h) { delete p; p=h.p; h.p=nullptr; return *this; } // transfer ownership
Handle(const Handle&) = delete; // no copy
Handle& operator=(const Handle&) = delete;
// ...
};
What does "transfer ownership" mean?
Why is the copy ctor equated to "delete"? how is it useful?
Please if someone can add a few examples with explanation, it would be a great help.
It's a move constructor, the special && syntax introduced in C++11 takes a rvalue reference, so a reference to a variable which has no name and can't be referenced anywhere else inside the code.
What happens in the constructor is that the Handle takes the ownership of the Handle passed through the move constructor in the way that it steals (pass me the term) the T* p inside by assigning its value to its own variable and then setting nullptr to the variable of the rvalue passed.
This is used because you don't really need to copy an rvalue, since that value won't be used anymore in the code, so it's safe to just take its data, this avoids a, possibly costly, copy constructor.
In C++ you had copy constructors and copy operators, which were expensive if your object was big. Now in C++11 you have move constructor and move operator which says "take everything from the source and kill it".
mybigthing y ;
...
mybigthing x( move(y)) ;
y is created with lots of stuff internally. after x(y), y is now empty and all the big stuff is in x.
One of the main reasons for this is to make returning big objects from functions free:
mybigthing f()
{
mybigthing tmp ;
...
return tmp ;
}
{
mybigthing y= f() ;
}
In c++03, this would be horrible performance wise. Now its free. The compilers are required to actually use y as the temporary inside of f() and never do any copies.
transfer ownership means if you do a=b the contents of b belong to a and does not exist in b anymore. This makes more sense in the example {A a; dosomething(a); return a;}. a exist locally in the function. It's contents are being moved into the return value. If A is a typedef for std::string it would mean the string internals have been moved instead of making a copy of a intentionally long string (html page maybe). However I believe string has a copy on write flag so it wouldn't make a copy in that situation but other classes may not bother to implement a copy on write.
The reason the constructor and assignment operator (which are move, not copy) delete is because the current p may be pointing to something. Not freeing it means a memory leak.
about your second question:
Why is the copy ctor equated to "delete"? how is it useful?
Here is an answer:
http://www.developerfusion.com/article/133063/constructors-in-c11/
C++11 Explicitly Deleted Constructors
C++11 also supports the concept of explicitly deleted constructors.
For example, you can define a class for which you do not want to write
any constructors and you also do not want the compiler to generate the
default constructor. In that case you need to explicitly delete the
default constructor:
class MyClass { public:
MyClass() = delete; };
I have this problem, there is a function foo() as follows,
vector<ClassA> vec;
void foo()
{
ClassA a; //inside foo, a ClassA object will be created
a._ptr = new char[10];
vec.push_back(a); //and this newly created ClassA object should be put into vec for later use
}
And AFAIK, vec will invoke ClassA's copy-ctor to make a copy of the newly created object a, and here is the problem. If I define ClassA's copy-ctor the usual way,
ClassA::ClassA(const ClassA &ra) : _ptr(0)
{
_ptr = ra._ptr;
}
then object a and its copy (created by vec) will have pointers _ptr pointing to the same area, when foo finishes, a will call the destructor to release _ptr, then a's copy in vec will be a dangling pointer, right? Due to this problem, I want to implement ClassA's copy-ctor this way,
ClassA::ClassA(ClassA &ra) : _ptr(0) //take non-const reference as parameter
{
std::swap(_ptr, a._ptr);
}
Is my implementation ok? Or any other way can help accomplish the job?
To answer your titular question: Yes, any constructor for a class T that has one mandatory argument of type T & or T const & (it may also have further, defaulted arguments) is a copy constructor. In C++11, there's also a move constructor which requires one argument of type T &&.
Having a non-constant copy constructor that actually mutates the argument gives your class very unusual semantics (usually "transfer semantics") and should be extensively documented; it also prevents you from copying something constant (obviously). The old std::auto_ptr<T> does exactly that.
If at all possible, the new C++11-style mutable rvalue references and move constructors provide a far better solution for the problem of "moving" resources around when they're no longer needed in the original object. This is because an rvalue reference is a reference to a mutable object, but it can only bind to "safe" expressions such as temporaries or things that you have explicitly cast (via std::move) and thus marked as disposable.
C++11 introduced move constructors for this exact purpose:
ClassA::ClassA(ClassA&& ra)
: _ptr(ra._ptr)
{
ra._ptr = nullptr;
}
Alternatively you can declare _ptr to be a shared pointer:
std::shared_ptr<char[]> _ptr;
and then default denerated copy constructor will do just fine.
You should not copy the pointer, you should copy the context that the pointer is pointing to. You should also initialize the class by telling it how many elements you want, instead of allocating it by accessing a public pointer.
Since you want to copy the object, not move it, you should allocate resources in the new object when copying.
class A {
int* p_;
int size_;
public:
A(int size)
: p_(new int[size]()),
size_(size) {
}
A(const A &a)
: p_(new int[a.size_]),
size_(a.size_) {
std::copy(a.p_, a.p_ + a.size_, p_);
}
...
};
int main () {
A a(10);
vec.push_back(a);
}
However, if you know that the object you will copy isn't used after it's copied, you could move it's resources instead.
The problem with your implementation is that you will not be able to pass temporary objects as arguments for this copy-ctor (temporaries are always const). Like already mentioned the best solution would be to move to c++11 and use move semantics. If it is not possible shared_array can be an alternative.
Additional comment:
Avoid these kind of problems creating the object with new and storing pointers to the object in the vector.
myClassVar = MyClass(3);
I expected destructor being called on the previously created myClassVar on the left.
But it is actually being called on the new object that's created by MyClass(3).
My full test code and output follows..
edit
How do I fix the problem?
Implement an assignment operator?
MyClass actually has pointers, and MYSQL_STMT*, I wonder how should I deal with MYSQL_STMT* variable.
I just need MyClassVar(3) object not the MyClassVar() which was first created when ClientClass object was created.
I came across this situation fairly often, and wonder if there's a good way to do it.
#include <stdio.h>
class MyClass
{
public:
MyClass() { printf("MyClass %p\n", this); }
MyClass(int a) { printf("Myclass(int) %p\n", this); }
~MyClass() { printf("~MyClass %p\n", this); }
private:
int mA;
};
class ClientClass
{
public:
void Foo()
{
printf("before &myClassVar : %p\n", &myClassVar);
myClassVar = MyClass(3); // this is the important line
printf("after &myClassVar : %p\n", &myClassVar);
}
private:
MyClass myClassVar;
};
int main()
{
ClientClass c;
c.Foo();
return 0;
}
MyClass 0x7fff5fbfeba0
before &myClassVar : 0x7fff5fbfeba0
Myclass(int) 0x7fff5fbfeb70
~MyClass 0x7fff5fbfeb70 // <--- here destructor is called on the newly created object
after &myClassVar : 0x7fff5fbfeba0
~MyClass 0x7fff5fbfeba0
Here's how the critical line breaks down:
myClassVar = MyClass(3);
First, MyClass(3) calls constructor and returns the object.
Second, myClassVar = copies the object to myClassVar.
Then the statement ends. The object (which is an immediate) is dead, and thus the destructor is invoked.
EDIT :
As for how to get around this. The only way I can think of is to use a placement new. I'm not sure if there's a better solution other than making a "set" method.
myClassVar = MyClass(3);
myClassVar continues to exist after this line. The lifetime of MyClass(3) ends at the semicolon.
As the other posts mentioned the object with the custom constructor MyClass(3) gets destroyed after the assignment operation myClassVar = MyClass(3). In this case you do not need a custom assignment operator because the compiler generated one copies the member mA to the already existing object myClassVar.
However since MyClass defines its own destructor you should adhere to the rule of three, which mandates that in such a case you should implement a custom assignment operator as well.
Responding to your edit: how do you fix what problem? It's not clear
what the problem is. If your class needs a destructor (and there's no
polymorphism in play), it probably needs both an assignment operator and
a copy constructor. Similarly, when "tracking" construcctions and
destructions, you should probably provide both as well, since they will
be called.
Otherwise: if the problem is that you're constructing and then
assigning, rather than constructing with the correct value immediately,
the simple answer is "don't do it". The compiler does what you tell it
to. If you write:
MyClass var;
var = MyClass(3);
you have default construction, followed by the construction of a
temporary, assignment, and the destruction of the temporary. If you
write:
MyClass var(3);
or
MyClass var = 3;
you only have one construction. (Note that despite appearances, there
is no assignment in the last snippet. Only construction.)
For class members, this difference appears in the way you write the
constructor:
ClientClass::ClientClass() { var = MyClass(3); }
is default construction, followed by creation, assignment and
destruction of a temporary;
ClientClass::ClientClass() : var( 3 ) {}
is just construction with the correct value. (Rather obviously, this
second form is preferred.)
i m trying to make a simple program ( & yes , it is a homework ) that can generate Dates , & like most of normal people : i made my Class attributes private , i tried to send the same type that i m working on to the constructor but the complier have not accept it , i did some research & i found out that in cases like that people generously send a const "type" reference to the constructor witch meant to me that have not understand OOP well
so why do we have to send the const " type " reference instead of just the types name to the constructor ? & please give me some links or websites for beginners
here is a peace of my Code :
class Date {
int d ;
int m ;
int y ;
public :
Date();
Date(int , int , int);
Date(const Date &);// my question is : why do we have to write this instead of Date( Date )
};
PS : sorry for my English
To paraphrase our question:
why do we have to write Date(const Date &) instead of Date(Date)?
I'm going to split this into two parts, the first answering why a copy constructor needs to take its argument per reference, the second why this needs to be a const reference.
The reason a copy constructor needs to take its argument per reference is that, for a function that's taking an argument per copy void f(T arg), when you call it f(obj), obj is copied into arg using T's copy constructor. So if you want to implement the copy constructor, you'd better not take the argument by copy, because this would call the copy constructor while invoking it, leading to an endless recursion. You can easily try this yourself:
struct tester {
tester(tester) {std::cout << "inside of erroneous copy ctor\n";}
};
int main()
{
tester t1;
std::cout << "about to call erroneous copy ctor\n";
tester t2(t1);
std::cout << "done with call erroneous copy ctor\n";
return 0;
}
That program should only ever write one line and then blow the stack.
Note: As Dennis points out in his comment, actually this program is not guaranteed to compile, so, depending on your compiler, you might not really be able to try it.
Bottom line: A copy constructor should take its argument by reference, because taking it per copy would require the copy constructor.
That leaves the question of why it is const T& and not simply T&? In fact, there are two reasons for that.
The logical reason is that, when you invoke the copy constructor, you do not expect the object copied from to change. In C++, if you want to express that something is immutable, you use const. This tells users that they can safely pass their precious objects to your copy constructor, because it won't do anything with it except read from it. As a nice side effect, if you implement the copy constructor and accidentally try to write to the object, the compiler throws an error message at you, reminding you of the promise made to the caller.
The other reason is that you cannot bind temporary objects to non-const references, you can only bind them to const references. A temporary object is, for example, what a function might return:
struct tester {
tester(tester& rhs) {std::cout << "inside of erroneous copy ctor\n";}
};
tester void f()
{
tester t;
return t;
}
When f() is called, a tester object is created inside, and a copy of it is then returned to the caller, which might then put it into another copy:
tester my_t = f(); // won't compile
The problem is that f() returns a temporary object, and in order to call the copy constructor, this temporary would need to bind to the rhs argument of tester's copy constructor, which is a non-const reference. But you cannot bind a temporary object to a non-const reference, so that code won't compile.
While you can work around this if you want (just don't copy the temporary, but bind it to a const reference instead, which extends the temporary's lifetime to the end of the reference's lifetime: const tester& my_t = f()), people expect to be able to copy temporaries of your type.
Bottom line: A copy constructor should take its argument by const reference, because otherwise users might not be willing or able to use it.
Here's one more fact: In the next C++ standard, you can overload functions for temporary objects, so-called rvalues. So you can have a special copy constructor that takes temporary objects overloading the "normal" copy constructor. If you have a compiler that already supports this new feature, you can try it out:
struct tester {
tester(const tester& rhs) { std::cout << "common copy ctor\n"; }
tester( tester&& rhs) { std::cout << "copy ctor for rvalues\n"; }
};
When you use the above code to invoke our f()
tester my_t = f();
the new copy constructor for rvalues should be called when the temporary object returned by the call to f() is copied to my_t and the regular copy constructor might be called in order to copy the t object from inside of f() to the returned temporary. (Note: you might have to disable your compiler's optimization in order to see this, as the compiler is allowed to optimize away all the copying.)
So what can you with this? Well, when you copy an rvalue, you know that the object copied from is going to be destroyed after the call to the copy constructor, so the copy constructor taking an rvalue (T&&) could just steal the values from the argument instead of copying them. Since the object is going to be destroyed anyway, nobody is going to notice.
For some classes (for example, for string classes), moving the value from one object to another could be much cheaper than copying them.
if I understood your question correctly, to avoid making copies/calling constructor of object.
void function(const T&); // does not create new T
void function(T&); // does not create newT, however T must be modifiable (lvalue)
void function(T); // creates new T
for simple types creating new copy is trivial (and often optimized away by compiler).
For complex object, creating new copy may be very expensive.
Hence you pass it by reference.
https://isocpp.org/wiki/faq/references
https://isocpp.org/wiki/faq/ctors
if you are asking why can not do the following:
struct type {
type(type);
};
Is because this would lead to infinite recursion, since constructor depends on itself
you can do this however
struct type {
type(type, int);
};
since this constructor is different from synthesized type(const type&)
http://en.wikipedia.org/wiki/Copy_constructor
In addition to #aaa's answer, I will try to answer the const part. The const part simply means that the object you are passing logically does not change. This makes sense, because when a copy constructor is called with a Date object argument d, d should not be modified at all!
You can remove the const and your code will still work the same way. However, const provides the additional security that you can never modify the variable marked as const. In your case, this means you can not call any of the non-const method of Date. This is enforced by the compiler at compile-time.
Historically this is the reason for introducing references to the language. Here's an explanation:
In C you can pass values to parameters by value (void f(struct custom_type i)) or by pointer (void g(struct custom_type* i)).
With POD values (int, char, etc.) passing by value is not a problem, but if you are looking at complex structures, then the stack grows too quickly by placing entire structures on stack for function calls. That is why in C you tend to pass structures as parameters by pointer, even if the function doesn't modify them.
In C++ there are cases where neither option worked:
passing by pointers involves a counter-intuitive syntax for operators (if you define operator + for a class custom_type writing custom_type a, b, c; a = &b + &c; is counterintuitive as a doesn't get assigned the sum of the addresses. Furthermore if you wanted to be able to assign the sum of the values to a and the sum of the addresses to a, you would have to somehow differentiate between the cases, by syntax).
passing by value is impossible or undesired in the case of copy constructors. In your case, if you have Date(Date d) {} and assignment Date a; Date b(a); what you get is that a copy of a is created just to be passed as a parameter to the constructor of b. This leads to infinite recursion, as creating a copy of a to pass as a parameter involves is the same as Date d = a; b = Date(d);.
For these reasons (and there may have been others) a decision was made to create references: data types that looks syntactically like a value type, but behave like pointers (that is, it points to the value of another variable, but you access it like a variable, not like a pointer).
Regarding the reason why you need const in the declaration, it is so that your constructor will accept temporary objects. As you cannot modify the value of a temporary references if your constructor doesn't accept const& you can only use the copy constructor for non-const stable objects.
That is, if you have:
class Date
{
public:
Date(Date& other); // non-const reference
...
you can write:
Date a;
Date b = a;
but not:
Date someFunction() { return Date(xxx); }
Date a = someFunction(); // someFunction returns a temporary object
neither:
const Date someImportantDate;
Date a = someImportantDate; // cannot pass const value to non-const