Can anyone explain why the copy constructor here is called two times?
class A
{
int i;
public:
A(){cout<<"IN constr"<<endl;};
A(int x):i(x) {};
A (A &a)
{
cout<<"in copy"<<endl;
i= a.i;
}
};
class MyClass {
A var;
public:
MyClass(A a):var(a) {
}
};
int main() {
A a1;
MyClass m(a1);
return 0;
}
When i run the code out put is:
IN constr
in copy
in copy
I can understand one time when it copies a into the variable var, but when it gets called second time?
You are passing the constructor argument by value, which is where your second copy comes from. You'll get just one copy if you change the constructor signature to the more canonical C++:
MyClass(const A& a)
: var(a)
{
}
That's called argument passing by const reference, and pre-C++11 it was basically the go-to way of passing arguments to functions.
If you know you will be dealing with temporary objects passed as function arguments though, then C++11 and onwards also have pass-by-rvalue-reference - see e.g. Pass by value vs pass by rvalue reference for more information.
The first copy is from a1 to the parameter a of the MyClass constructor, the second one is from the parameter a to the member var.
If you want to reduce the number of copies, you have (at least) two options:
Pass a const reference to the constructor as mentioned by Joris:
MyClass(A const &a) : var(a) {
}
If A can be efficiently moved, take a by value and move to the member:
MyClass(A a) : var(std::move(a)) {
}
That way, a user that does not need his A anymore can move it into the new MyClass instance, while a user that still needs the A can pass it by value.
void useA(A &a);
void doSomethingWithM(MyClass & m);
void functionThatNeedsAAgain() {
A myImportantA;
MyClass m {myImportantA}; // copy myImportantA once
useA(myImportantA);
doSomethingWithM(m);
}
void functionThatDoesNotNeedAAgain() {
A tempA;
// no copy needed, as tempA will never be used again
MyClass m {std::move(tempA);
doSomethingWithM(m);
}
The third option would be to provide constructors from both const A& and A&& but I would weigh the code duplication against the benefit.
If you want to know how far this can be taken if A happens to be std::string and you want to cover the construction of temporary As, watch this excellent talk by Nicolai Josuttis.
Related
I have a long class with a lot of data members. I want to write a copy constructor for it. But, if I write my own copy constructor, I lose access to the default copy constructor.
I just want to repair a few pointers in my own copy constructor. So I want to have a shallow copy of the object which can be done by the default copy constructor.
Is there a possibility to access the default copy constructor when I have my own copy constructor?
Wrap the things you don't want to change in a struct, and derive (privately) from it. In your copy constructor, simply invoke the copy constructor of your base class.
No you cannot have both default and your own copy c-tor.
But there are two workarounds with this problem:
1 Enclose your pointers in some class with defined copy semantics
Example:
class A {
public:
private:
int trivial1;
int trivial2;
...
SomePointer nontrivialMember;
};
class SomePointer {
public:
SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
int* nonTrivialMember;
};
2 Enclose the trivial parameters in some trivial structure
Example:
class A {
public:
A(const A& o) : data(o.data) {
// non trivial part
}
private:
struct Data {
int trivial1;
int trivial2;
...
} data;
int* nontrivialMember;
};
I would always select the first solution.
[UPDATE]
There is also 3rd solution, very similar to my second, enclose your trivial part in privately inherited base class. I'd still prefer the 1st solution.
The simplest approach to this would be to wrap up the pointers into classes that will perform the 'repair' manually in their copy constructor, then you can happily use the default copy constructor.
No, there is no way to call the default copy constructor from an user defined copy constructor.
You can either use the default or your own, not both. If you want to choose different functionality for different objects you should just write a member function that handles that case.
void DeepCopy(MyClass* rhs);
For example.
You cannot access default copy ctor if you created your own - compiler just doesn't generate it. But ther is workaround - split you class into data structure and logic.
See example:
struct Data
{
int i;
std::string s;
Data(): i(), s() {}
};
class Code: private Data
{
public:
Code() {}
Code(const Code& rhs): Data(rhs) // Call default copy ctor
{
i = 42; // Your copy part
return *this;
}
};
My solution is a simple memcpy() instead of the impossible call to the implicit (compiler generated) copy constructor, as the example shown below:
Class Foo
{
public:
...
Foo (Foo & other) {
// copies trivial part (and non-trivial part with possible wrong values)
memcpy(this, &other, sizeof(Foo));
// your non-trivial part here, overwrites the wrong values (if any) above.
}
}
Yet the side-effect is that the memcpy() will also copy those non-trivial part, which is a waste. If the non-trivial part does not contain too much space, I will prefer my solution.
For example, a class like below wastes only 4 byte copy of the one pointer, assuming the size of a pointer is 4 bytes.
Class Bar
{
int x, y, z;
// memcpy() wastes these 4 bytes copy,
// since actual copy constructor wants a new string
string *s;
}
This worked for me... (C++11, don't know if it works on older std)
Not sure why it doesn't end up in an endless loop.
class Foo {
public:
Foo(const Foo &orig) {
*this = orig;
... exchange pointers, do own stuff
}
I am trying to come up with the most efficient (i.e. minimal amount of copies) implementation of the following. I have a queue which is used to execute std::function<void()> objects at some later point in time. The queue can only take trivial data types and thus I need to pass it a pointer to a std::function rather than the std::function itself (i.e. the queue holds std::function<void()>* types).
Ideally, if a piece of data is captured (by value) in a lambda, only a SINGLE copy of this data should be made throughout the process of creating an std::function and adding it to the queue.
Here is an example I have been playing with:
std::function<void()>* invoke(const std::function<void()>& fn) {
printf("invoke()\r\n");
return new std::function<void()>(fn);
}
which I would use like so
class Base {
public:
virtual void sayHello() const = 0;
};
class A : public Base {
public:
A() {
printf("A::A()\r\n");
}
A(const A& a) {
printf("A copy constructor\r\n");
}
A(const A&& a) {
printf("A const move constructor\r\n");
}
A(A&& a) {
printf("A move constructor\r\n");
}
A& operator=(A&& other)
{
printf("A move assignment operator\r\n");
return other;
}
void sayHello() const override { printf("A says hello\r\n"); }
};
int main() {
A myA;
printf("invoking lambda which calls myA.sayHello()\r\n");
std::function<void()> *fn = invoke([myA](){
myA.sayHello();
});
return 0;
}
Since the lambda is capturing the object (myA) by value, a copy is made when the lambda is originally created. Now, since the lambda you see in main() is "temporary" (only used in the call to invoke) there should really only ever by a single copy of the lambda hanging around and thus only a single (additional) copy of myA.
However, here is an example of my output:
invoking lambda which calls myA.sayHello()
A copy constructor
A move constructor
invoke()
A copy constructor
It appears that, when I create a new std::function on the heap, it is COPYING the lambda (and thus myA) instead of just moving it, which is what my desired behavior is since the original lambda and std::function (the one created automatically when passing the lambda to the invoke function) are only temporary anyways.
I feel like I am very close, but am misunderstanding something here. Could anyone help?
Thanks!
EDIT
Based upon all the discussion here, I have made a few modifications to my code. Now I am stepping this up to a more complicated example as follows:
//Same A and Base classes as above
inline static void invoke(std::function<void()> fn) {
printf("invoke(std::function<void()> fn)\r\n");
std::function<void()>* newF = new std::function<void()>(std::move(fn));
(*newF)();
delete newF;
printf("return\r\n");
}
int main() {
printf("Starting Tests...\r\n");
A myA;
invoke([myA](){
myA.sayHello();
});
return 0;
}
Which has the following, unexpected output:
Starting Tests...
A::A()
A copy constructor
A move constructor
invoke(std::function<void()> fn)
A says hello
A::~A()
return
A::~A()
A::~A()
I can't figure out why there is a 3rd call to the destructor since only 2 copies of the A object should be in existence (the original copy in main() and the copy made by the copy constructor in the lambda).
Your example does not work because you are trying to std::move from a const reference. This will result in a type std::function<...> const&&, but the move constructor of std::function only accepts std::function<...>&& (without the const). This is not unusual in C++, as const rvalue references are a weird corner case of the language that don't make much sense conceptually. In particular, you cannot reasonably move from a const rvalue reference, because you won't be allowed to make any changes to the source.
If the intention is to guarantee that no copies happen, you should accept the argument via rvalue reference:
std::function<void()>* invoke(std::function<void()>&& fn) {
printf("invoke()\r\n");
return new std::function<void()>(std::move(fn));
}
Note that this restricts the function to only work with rvalue arguments. If you prefer a more flexible design, consider max66's answer.
Maybe... using perfect forwarding you can transform a copy in a move.
template <typename F>
auto invoke (F && fn) {
printf("invoke()\r\n");
return new std::function<void()>(std::forward<F>(fn));
}
You get
A::A()
invoking lambda which calls myA.sayHello()
A copy constructor
invoke()
A move constructor
A move constructor
Unrequested Suggestion: avoid like the plague direct memory allocation management; use smart pointer instead
template <typename F>
auto invoke (F && fn) {
printf("invoke()\r\n");
return std::unique_ptr<std::function<void()>>
{new std::function<void()>(std::forward<F>(fn))};
}
I have a class that looks somewhat like this:
class S
{
public:
int* data;
S() : data(new int[10]) {}
};
The constructor allocates the memory of 10 integers, and the default copy constructor as expected merely copies the pointer itself rather than the content.
Even if there is an instance of S that has const modifier, I can modify the data that data points to, since that data itself does not have const modifier. I could avoid this by making data private and only allowing write access via a non-const method like so:
class S
{
private:
int* data;
public:
S() : data(new int[10]) {}
int& operator(size_t i)
{
return data[i];
}
const int& operator(size_t i) const
{
return data[i];
}
};
But now I can use the copy constructor to circumvent the constness of the instance of S like so:
void main()
{
const S a; // Allocates memory
S b(a); // Also points to memory allocated for a
b(1) = 3; // Writes to a even though it is not supposed to be mutable
}
What would be an elegant way to solve this problem (potentially using templates)?
The data pointed to by an instance of const S should not be mutable at all using only this instance.
Copy constructor should only copy pointer, but not make a deep copy of the data.
Both a const S and an S should be creatable via a copy constructor given an instance of S such that the const instance cannot modify the data, but the non-const instance can.
It is possible to know in the copy constructor if the object being copied is const by providing two different copy constructors, one which takes a const parameter and one which does not. The compiler will select whichever version matches the passed parameter. Set a flag in the constructor so it can throw an error when a non-const operation is performed.
The best way to avoid the leaked memory shown in the question is to used a smart pointer like std::shared_ptr rather than a raw pointer. Unfortunately shared_ptr is meant for single objects, not arrays; workarounds are possible as in this StackOverflow question. I'm not going to try to solve this now, the code below still has the leak.
To be complete you should follow the Rule of Three and provide an operator= and destructor as well. I left this as an exercise for the reader.
class S
{
private:
int* data;
bool is_const;
public:
S() : data(new int[10]), is_const(false) { data[1] = 42; }
S(const S& other) : data(other.data), is_const(true) {}
S(S& other) : data(other.data), is_const(false) {}
int& operator()(size_t i)
{
if (is_const)
throw std::logic_error("non-const operation attempted");
return data.ptr[i];
}
const int& operator()(size_t i) const
{
return data.ptr[i];
}
};
See it in action: http://ideone.com/SFN89M
Delete the copy constructor (and assignment operator) for S. Create a new proxy class (SCopy) that holds a pointer to an S object (which is passed in to the constructor for SCopy). SCopy would then implement the const int &operator() const and not the non-const version.
This would then allow you to implement a destructor in S that would free the memory you're currently leaking.
I am new to C++ and I do not know how to solve the following problem.
The class Foo has a constructor which creates a array of doubles of a given size. The destructor deletes this array. The print method prints the array.
#include <iostream>
class Foo {
private:
int size;
double* d;
public:
Foo(int size);
~Foo();
void print();
};
Foo::Foo(int size)
{
this->size = size;
d = new double[size];
for (int i = 0; i < size; i++)
{
d[i] = size * i;
}
}
Foo::~Foo()
{
delete[] d;
}
void Foo::print()
{
for (int i = 0; i < size; i++)
{
std::cout << d[i] << " ";
}
std::cout << std::endl;
}
Now I have a function func(Foo f) which does nothing.
void func(Foo f){}
int main()
{
Foo f(3);
f.print();
func(f);
Foo g(5);
f.print();
return 0;
}
Executing this code gives the following output:
0 3 6
0 5 10
Although I am printing f both times, somehow the values inside the array have changed.
I guess that the destructor of Foo is called on parameter Foo f after the execution of func(Foo f) and this frees the allocated memory for d, which is reallocated for Foo g(5). But how can I avoid this without using vectors or smart pointers?
The problem is with the design of the class. The default copy constructor will create a new instance of Foo when passed by value into the free standing function named func.
When the instance of Foo named f exits scope then the code invokes the user-provided destructor that deletes the array of doubles. This opens the code to the unfortunate situation of deleting the same array twice when the original instance of Foo named f exits scope at the end of the program.
When run on my machine, the code does not produce the same output. Instead I see two output lines of 0 3 6 followed by fault indicating the double free operation.
The solution is to avoid the copy by passing by reference (or by const reference): void func(Foo const &f) { } or to supply a valid copy constructor that makes a deep copy of the underlying array. Passing by reference is just a bandaid that avoids exercising the bug.
Using std::vector<double> fixes the problem because the default copy constructor will perform a deep copy and avoid double deallocation. This is absolutely the best approach in this small example, but it avoids having to understand the root of the problem. Most C++ developers will learn these techniques then promptly do what they can to avoid having to write code that manually allocates and deallocates memory.
You should probably pass the object as a reference func(Foo& f) or - if you do not want to modify it at all - as a constant reference func(const Foo& f). This will not create or delete any objects during the function call.
Aside from that, as others have already mentioned, your class should better implement the Rule of Three.
When you pass a value to a function, it is supposed to be copied. The destructor is run on the copy and should no effect on the original object. Foo fails to implement a copy constructor, so compiler provides the default one which simply performs a member-wise copy of the struct. As a result, the "copy" of Foo inside Func contains the same pointer as the original, and its destructor frees the data pointed to by both.
In order to be usable by idiomatic C++ code, Foo must implement at least a copy constructor and an assignment operator in addition to the destructor. The rule that these three come together is sometimes referred to as "the rule of three", and is mentioned in other answers.
Here is an (untested) example of what the constructors could look like:
Foo::Foo(const Foo& other) {
// copy constructor: construct Foo given another Foo
size = other->size;
d = new double[size];
std::copy(other->d, other->d + size, d);
}
Foo& Foo::operator=(const Foo& other) {
// assignment: reinitialize Foo with another Foo
if (this != &other) {
delete d;
size = other->size;
d = new double[size];
std::copy(other->d, other->d + size, d);
}
return *this;
}
Additionally, you can also modify functions like func to accept a reference to Foo or a constant reference to Foo to avoid unnecessary copying. Doing this alone would also happen fix the immediate problem you are having, but it would not help other issues, so you should definitely implement a proper copy constructor before doing anything else.
It's a good idea to get a good book on C++ where the rule of three and other C++ pitfalls are explained. Also, look into using STL containers such as std::vector as members. Since they implement the rule of three themselves, your class wouldn't need to.
One problem is that calling func creates a bitwise copy. When that copy goes out of scope the destructor is called which deletes your array.
You should change void func(Foo f){} to void func(Foo& f){}.
But better yet you add a create copy constructor or add a private declaration to stop it being called unexpectedly.
Consider the following :
class A
{
public:
int xx;
A(const A& other)
{
cout << "A cctor" << endl;
/* do some stuff */
}
A(int x) : xx(x) {} /* conversion constructor */
};
int main()
{
A a = 1;
A other = a;
return 0;
}
Is it right to say that CCtor converts from const to non-const in this case (and also in general) ?
Thanks ,Ron
A copy constructor creates a new copy of an existing object, that object may or may not be const. The const in A::A(const A& other) just says we are not going to change other in the copy ctor. Indeed if you attempt to modify other inside the ctor the compiler will moan at you.
The created object also may or may not be const depending on how you declare it.
No idea what you mean. A(const A&) is a typical copy-ctor, which has a "read-only" access to its only argument. If you pass anything const, everything is fine. If you pass anything non-const, for ctor it becomes const. A a = 1 is a conversion ctor, as you said. A other = a is a copy ctor. What's the question?
Regarding your question's title, in C++ there's no fair way to convert const to non-const.
class A
{
public:
int xx;
A(const A& other)
{
cout << "A cctor" << endl;
/* do some stuff */
// other is const here - you can only call its
// const methods and read all its data members
}
A(int x) : xx(x) {} /* conversion constructor */
// at this point, x is not const, but it's a copy
// of an object you've passed here, not the object itself
// you can change x, it just doesn't matter - you
// change the copy
};
int main()
{
A a = 1; // a is not const, 1 is passed "by value", since it's primitive type
A other = a; // a is not const, other is not const, a is passed by const reference
return 0;
}
Constructor initializes a new copy. And there is no problem in copying from a constant.
No conversion is involved.
What do you mean by CCtor converts from const to non-const?
If you mean, the non-const object gets created from the const object by invoking the copy-constructor, then yes. But that doesn't mean the const-object itself becomes non-const inside the copy-constructor (or at the call site). It only means that the newly constructed object is created by copying the existing object which is passed as const reference to the copy-constructor.
No the copy constructor creates an copy of the class object by taking another class object as the parameter.
Since in order to construct the new object being passed as parameter is not required to be modified it it passed as an const.
No, it's not converting to a non-const object. Consider this:
A a(42);
const A another = a;
Here, another is a const object, created from a non-const object.
More important, however, is that a constructor creates a new object from an existing one. Whether that new object is const or not does not depend on the existing object. All four possible combinations of const/non-const old/new objects are possible.
In the sense that the A(int) constructor converts from int to A, yes it's true that your copy ctor A(const A&) "converts" from const A to A. For that matter it also "converts" from non-const A to A, since the const reference parameter can bind to either.
And since the same constructor is used to create a const object as to create a non-const one, that copy ctor can also "convert" from A or const A to const A.
I've used "convert" in quotes just because converting from a type to itself or a cv-qualified version of itself is perhaps a confusing use of the term, normally you just call that "copying" rather than conversion.
The constructor parameter can bind to an instance of a derived class of A too, so you might say that it converts derived classes to A. That's normally called "slicing".
Strictly speaking it's not the copy ctor itself that converts anything, but a conversion to A (whether a cast or an implicit conversion) does depend on using a matching constructor. So I suppose the constructor can claim a large part of the credit.