Adding functionality to a default copy constructor [duplicate] - c++

This question already has answers here:
How can I extend a compiler generated copy constructor
(5 answers)
Closed 5 years ago.
I have a question. Say I have a class A, for which I'm perfectly happy with the default copy constructor.
Can I add functionality to this default copy constructor without re-writing all its work again?
Trivial example:
class A
{
public:
A(int n) : data(n) { };
private:
int data;
};
Suppose I want to print the message "Copy constructor!" each time a copy constructor is called. For this simple case I would just write my own copy constructor, which takes charge of the shallow copy explicitly, and also prints out the message. Is there a way to add the message printing (or whatever other functionality I want) on top of the default copy constructor, without writing explictly the shallow coyp?

Suppose I want to print the message "Copy constructor!" each time a copy constructor is called. For this simple case I would just write my own copy constructor, which takes charge of the shallow copy explicitly, and also prints out the message.
Yes, you need to provide your copy constructor explicitely and add that printing out the message.
class A
{
public:
A(int n) : data(n) { };
// You need to add tis:
A(const& A rhs) : data(rhs.data) {
std::cout << "Copy constructor!" << '\n';
}
private:
int data;
};
Is there a way to add the message printing (or whatever other functionality I want) on top of the default copy constructor, without writing explictly the shallow coyp?
No, there isn't.

Related

Why should i use copy constructor? [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 11 months ago.
class person
{
private:
string p_name;
int p_age;
public:
person(string name, int age){
p_name = name;
p_age = age;
}
person(const person &pers){
p_name = pers.p_name;
p_age = pers.p_age;
}
void print(){
cout << "Name: " << p_name << '\n';
cout << "Age: " << p_age << '\n';
cout << &p_age << '\n';
cout << '\n';
}
};
int main()
{
person obj1{"Name", 18};
obj1.print();
person obj2{obj1};
obj2.print();
return 0;
}
Here's my code, it works, but when i delete copy constructor in still works, so what is a point to use copy constructor?
In this example, there is absolutely no use. C++ automatically generates a copy constructor that does exactly what you just do here: Copies each constituent field.
You need to implement a copy constructor (and several other things) if your class is managing resources in some unusual way. Your person class is nice: It stores an int and a string by value, which is super predictable, so C++ does the right thing automatically. If you were storing raw pointers (say, an int*) then you'd need a copy constructor, as well as a copy assignment, move assignment, move constructor, and destructor.
But in modern C++, we try to avoid that. Instead of raw pointers, use references (int&) for borrowing data, unique pointers (std::unique_ptr<int>) for owning data, and shared pointers (std::shared_pointer<int>) for that rare situation where you need multi-ownership, and save raw pointers and custom Rule of Five methods for that incredibly rare situation where all of the above fail you.
when i delete copy constructor in still works
You're not deleting the copy constructor. You're just not providing a user-defined copy constructor. Note that there is a difference between "deleting a copy ctor" and "not providing one". In the latter case, the compiler will synthesize the copy constructor for you.
That synthesized copy constructor, memberwise-copies the data members of its argument into the object being created. This means that the copy ctor that will be synthesized for your class person, will just copy(initialize) both of the data members p_name and p_age from the passed argument similar to what you were doing manually. Note that the synthesized copy ctor will intialize the data members instead of assigning values to them from the passed argument. For example, the synthesized copy ctor for your class person will be equivalent to:
person(const person& rhs): p_name(rhs.p_name), p_age(rhs.p_age)
{
}
what is a point to use copy constructor?
As i said, the synthesize copy ctor just memberwise copies the data members of the passed argument into the object being created. But sometimes we want to customize this behavior. That is, sometimes we want that the copy ctor will do something specific to our needs, for which we provide the user defined copy ctor. One example is when our class is managing resources in ways that the synthesized copy ctor will not be able to.

Is there a way in C++ to deep copy only required variables in CCTOR? [duplicate]

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
}

C++ copy constructor compilation error [duplicate]

This question already has answers here:
Why copy constructor not invoked here
(2 answers)
Closed 8 years ago.
I have read some articles concerning this topic but still have problems to compile my own code.
I have class A:
class A
{
public:
List<int> data;
A(){}
A(A&){}
A& operator= (const A& a)
{
// copy the data from a to data
}
};
Class B will call class A:
class B
{
public:
A makeA()
{
A a;
return a;
}
A getA()
{
A a = makeA();
return a;
}
};
When I compile my code with g++ under Linux, I got:
no matching function for call to 'A::A(A)'.
It seems that the compiler has simply ignored the assignment operation. Can you help me out of this?
In order for this to compile, your copy constructor must take its parameter by const reference:
A(const A&){}
Adding const to your constructor signature fixes this problem (demo on ideone).
Since you are defining an assignment operator and a copy constructor, you should strongly consider adding a desctructor ~A() (see the Rule of Three).
The assignment operator is not used here.
A a = makeA();
This line is an initialization; it uses the copy constructor to copy the value returned by makeA into a. The compiler is complaining because A::A(A&) can't be used with a temporary; change it to the much more common form A(const A&) and things will be much better.
#Peter is right. The copy constructor A(A&){} wants to be A(const A&){}, instead. The reason is that A(A&){} tells the compiler to prepare to modify the A passed to the copy constructor, which does not really make sense, and certainly does not make sense in case the A you pass is a temporary.

Copy Constructor is not invoked [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why copy constructor is not called in this case?
Consider the sample program below:
#include <iostream>
using namespace std;
class sample
{
private:
int x;
public:
sample(int a=0) : x(a)
{
cout << "default ctor invoked\n";
}
sample(const sample& obj)
{
cout << "copy ctor invoked\n";
}
};
int main()
{
sample s2 = sample(20); //Line1
sample s3 = 20; //Line2
return 0;
}
In Line1, first the constructor of sample class is invoked explicitly with the argument 20. Then i expected the copy constructor to be invoked to initialize s2.
In Line2, first the constructor of sample class is invoked implicitly first with the argument 20. Here also i expected the copy constructor to be invoked to initialize s2.
In both cases, the copy constructor is not invoked? Why is this happening? I believe, there is something wrong with my understanding of the invocation of copy constructor. Could someone correct me where i am going wrong?
This is expected. It's called copy elision.
Your expectation is correct, but they made an exception in C++ (for performance) which allows the compiler to treat your expression as direct initialization of one instance while bypassing the copy constructor.
in first line it does not invoke copy constructor because you do not copy an object. You are assigning one object to other. C++ provide default = operator which perform shallow copy. And this is invoked implicitly. The constructor is called for right hand object and default constructor is invoked for the left hand object. After that default = operator is invoked.
For line 2, it use constructor that takes int parameters that you define. It is actually converter constructor because it takes an integer and creates object of your class. Thats why c++ use this as a converter constructor and when you try to assign an integer to your object, c++ invokes inplicitly this converter constructor.
I hope this helps you to understand.

What is a copy constructor in C++?

On page 6 of Scott Meyers's Effective C++, the term 'copy constructor' is defined. I've been using Schiltdt's book as my reference and I can find no mention of copy constructors. I get the idea but is this a standard part of c++? Will such constructors get called when a pass a class by value?
Yes, copy constructors are certainly an essential part of standard C++. Read more about them (and other constructors) here (C++ FAQ).
If you have a C++ book that doesn't teach about copy constructors, throw it away. It's a bad book.
A copy constructor has the following form:
class example
{
example(const example&)
{
// this is the copy constructor
}
}
The following example shows where it is called.
void foo(example x);
int main(void)
{
example x1; //normal ctor
example x2 = x1; // copy ctor
example x3(x2); // copy ctor
foo(x1); // calls the copy ctor to copy the argument for foo
}
See Copy constructor on Wikipedia.
The basic idea is copy constructors instantiate new instances by copying existing ones:
class Foo {
public:
Foo(); // default constructor
Foo(const Foo& foo); // copy constructor
// ...
};
Given an instance foo, invoke the copy constructor with
Foo bar(foo);
or
Foo bar = foo;
The Standard Template Library's containers require objects to be copyable and assignable, so if you want to use std::vector<YourClass>, be sure to have define an appropriate copy constructor and operator= if the compiler-generated defaults don't make sense.
Copy constructor will be called in then following scenarios:
When creating new objects from an existing object.
MyClass Obj1;
MyClass Obj2 = Obj1; // Here assigning Obj1 to newly created Obj2
or
MyClass Obj1;
MyClass Obj2(Obj1);
When passing class object by value.
void NewClass::TestFunction( MyClass inputObject_i )
{
// Function body
}
Above MyClass object passed by value. So copy constructor of MyClass will call. Pass by reference to avoid copy constructor calling.
When returning objects by value
MyClass NewClass::Get()
{
return ObjMyClass;
}
Above MyClass is returned by value, So copy constructor of MyClass will call. Pass by reference to avoid copy constructor calling.
The C++ FAQ link posted by Eli is nice and gbacon's post is correct.
To explicitly answer the second part of your question: yes, when you pass an object instance by value the copy constructor will be used to create the local instance of the object in the scope of the function call. Every object has a "default copy constructor" (gbacon alludes to this as the "compiler generated default") which simply copies each object member - this may not be what you want if your object instances contain pointers or references, for example.
Regarding good books for (re)learning C++ - I first learned it almost two decades ago and it has changed a good deal since then - I recommend Bruce Eckel's "Thinking in C++" versions 1 and 2, freely available here (in both PDF and HTML form):
http://www.ibiblio.org/pub/docs/books/eckel/
Copy Constructor is an essential part of C++. Even-though any C++ compiler provides default copy constructor if at all if we don't define it explicitly in the class, We write copy constructor for the class for the following two reasons.
If there is any dynamic memory allocation in the class.
If we use pointer variables inside the class. (otherwise it will be a shallow copy in
which 2 objects will point to the same memory location.)
To make a deep copy, you must write a copy constructor and overload the assignment operator, otherwise the copy will point to the original, with disastrous consequences.
The copy constructor syntax would be written as below:
class Sample{
public:
Sample (const Sample &sample);
};
int main()
{
Sample s1;
Sample s2 = s1; // Will invoke Copy Constructor.
Sample s3(s1); //This will also invoke copy constructor.
return 0;
}
A copy constructor is a constructor which does deep copy. You should write your own copy constructor when there is a pointer type variable inside the class. Compiler will insert copy constructor automatically when there is no explicit copy constructor written inside the code. The type of a copy constructor parameter should always be reference type, this to avoid infinite recursion due to the pass by value type.
below program explains the use of copy constructor
#include <iostream>
#pragma warning(disable : 4996)
using namespace std;
class SampleTest {
private:
char* name;
int age;
public:
SampleTest(char *name1, int age) {
int l = strlen(name1);
name = new char[l + 1];
strcpy(this->name, name1);
this->age = age;
}
SampleTest(const SampleTest& s) { //copy constructor
int l = strlen(s.name);
name = new char[l + 1];
strcpy(this->name, s.name);
this->age = s.age;
}
void displayDetails() {
cout << "Name is " << this->name << endl;
cout << "Age is " << this->age << endl;
}
void changeName(char* newName) {
int l = strlen(newName);
name = new char[l + 1];
strcpy(this->name, newName);
}
};
int main() {
SampleTest s("Test", 10);
s.displayDetails();
SampleTest s1(s);
cout << "From copy constructor" << endl;
s1.displayDetails();
s1.changeName("Test1");
cout << "after changing name s1:";
s1.displayDetails();
s.displayDetails();
cin.get();
return 0;
}