I Have just created a class with an integer variable and a pointer variable. After creating its object , I passed it to a function. Even after returning the function the program is not throwing the exception
#include"iostream"
using namespace std;
class A
{
public :
int i;
char *c;
void show();
};
void func(A obj);
int main()
{
A a;
a.i = 10;
a.c = "string";
cout << " Before Fun " << endl;
a.show();
cout << " Going To Call func " << endl;
func(a);
cout << " After func " << endl;
a.show();
return 0;
}
void A::show()
{
cout << " The valuses in Object are " << i << '\t' << c << endl;
}
void func(A aa)
{
cout << " The valuses in Object are " << aa.i << '\t' << aa.c << endl;
}
In The Func I am passing the object a (from main) and it would get copied in aa (stack of func). so after returning from the func if i call show ( the pointer c would be null of a), It would give me exception
But it is not happening . please help me to prove the requirement of copy constructor
Hide the copy constructor. That will cause a compilation error everywhere it is called implicitly.
class A
{
public :
int i;
char *c;
private:
A(const A& _other);
};
If no copy constructor is declared for an object, one is implicitly defined. This copy constructor copies each element of the object.
In your example, the call to func(a) will call this copy constructor, and so aa will be a copy of a (aa.i will be 10 and aa.c will point to the first element of "string").
If you are using C++11 you can do the following to remove the copy constructor
class A
{
public :
int i;
char *c;
void operator=(const A& _other) = delete;
A(const A& _other) = delete;
};
or even better:
class A : public NonCopyable // perhaps std:: or if you prefer boost, boost::
{
public :
int i;
char *c;
};
http://en.wikipedia.org/wiki/C++11#Explicitly_defaulted_and_deleted_special_member_functions
When you make a class, a null constructor and copy constructor exist implicitly.
So that is why it does not throw an exception.
However, if you define ANY constructor, you will then need to define others otherwise the rest of the constructors will be overwritten.
For example, you define a null constructor only. Then it will throw an exception. Because the implicitly defined copy constructor will be overridden.
This is one way of proving the need of a copy constructor.
An implicit copy constructor does exist if you do not define one explicitly. It is called in your func() function. A object is copied and assigned a value for its member i.
Result will be: that you do get with show() the value for i that you had before when calling func. This is with no surprise because you are not doing any assignment to members of A inside A.
Implicit copy constructor by the compiler provide member-wise copy. This is what you may need in most cases.
When is default constructor not sufficient ? you have pointer like members, and need a deep-copy of it. You don't want to copy the pointer (what copy constructor would do), but rather to have the object pointed to copied. But why do you need deep copy ? You don't want to copy the pointer (which is owned by any instance of the class), and end up calling twice destructor on the same pointer. From the second call to delete on this pointer, heap corruption ensues. You may also need copy constructor made explicit for shared_pointers.
Note that, for performance reasons, it is best pass object by const reference than by value.
In your case the copy constructor provided by compiler is present.
Modify your code and write a copy constructor as:
//Default and copy constructor
A()
{
i = 0;
c = NULL;
}
A(const A& _other)
{
cout<<"In copy cons"<<endl;
}
When you will modify the code as per above when func gets called then your own copy constructor gets called in this case you will get the junk values(can not predict)
And if you modify your copy constructor code as
A(const A& _other)
{
cout<<"In copy cons"<<endl;
i = _other.i;
c = new char [(strlen(_other.c) +1)];
strcpy(c,_other.c);
}
Now you can see the differnce in both outputs and the use of Copy constructor how and where it's used.
Related
I would like to ask a question about references and pointers in C++.
I am a beginner in C++ so I apologise for if the answer is trivial.
I have written the following code as part of a tutorial.
#include <iostream>
using namespace std;
class Deep {
private:
int *data;
public:
void set_data_value(int d) {*data = d;}
int get_data_value () {return *data;}
// Constructor
Deep (int d);
// Copy constructor
Deep (const Deep &source);
// Destructor
~Deep();
};
Deep::Deep(int d) {
data = new int;
*data = d;
}
Deep::Deep (const Deep &source)
: Deep (*source.data){ // main body of the constructor (delegation comes before the body)
cout << "Copy Constructor - deep copy" << endl;
}
Deep::~Deep() {
delete data;
cout << "Destructor deleting data" << endl;
}
void display_deep (Deep s) {
cout << s.get_data_value() << endl;
}
int main () {
Deep obj1 {100};
display_deep (obj1);
Deep obj2{obj1};
obj2.set_data_value(1000);
cout << endl;
return 0;
}
This code works. I will explain what I have done:
I defined a class named Deep to practice a deep copy. The pointer named data is private and I've included (and later defined) the function prototypes set_data_value and get_data_value.
set_data_value takes in an integer d, dereferences data and assigns the value d to it.
get_data_value simply returns the dereferenced value of data.
In the public domain also there is a constructor that accepts one integer d, a copy constructor which keeps the object constant and takes in a reference &source alongside a destructor.
Inside the copy constructor, I use a delegation constructor to improve the flow of the code.
However, if we observe the copy constructor
Deep::Deep (const Deep &source)
: Deep (*source.data){ // main body of the constructor (delegation comes before the body)
cout << "Copy Constructor - deep copy" << endl;
}
we know that this is run upon the pass-by-value nature of void display_deep (Deep s), so source is a reference to our s passed in. We then point to source and somehow obtain the value of data, which is then passed to the constructor.
How does this work? Does *source.data work as I described or does the compiler take a different route?
We then point to source and
There is no pointing to anything. In this line:
: Deep (*source.data)
You are just accessing the data inside source. Then you are dereferencing it. Just like you dereference *data to get the value inside it.
I wonder how this code run specifically line 54 (line2 = line1) although there is no overloading for the assignment operator ?
It seems from the output that neither the copy constructor nor the normal constructor were called and surprisingly it gets output as expected 199 199
#include <iostream>
using namespace std;
class Line
{
public:
int getLength();
Line( int len ); // simple constructor
Line( const Line &obj); // copy constructor
~Line(); // destructor
private:
int *ptr;
};
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj)
{
cout << "Copy constructor allocating ptr." << endl;
ptr = new int;
*ptr = *obj.ptr;
}
Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength()
{
return *ptr;
}
void display(Line obj)
{
cout << "Length of line : " << obj.getLength() <<endl;
}
// Main function for the program
int main()
{
Line line1(199);
Line line2(1);
line2 = line1; // How this is executed ??!
cout << line1.getLength() << " " << line2.getLength() << endl ;
/*display(line1);
display(line2);*/
cin.get();
return 0;
}
What you have there is undefined behavior. You assign line2 = line1 but have no user-defined assignment operator, so you use the default one provided by the compiler. And the default one simply copies all the fields, which in your case includes an int*. That gives you two copies of the same int*, leaks the value that line2 previously pointed to, and eventually double-deletes the one line1 originally pointed to. The second delete of the same pointer, which occurs when line1 goes out of scope at the end of main(), invokes undefined behavior.
If you have a destructor which frees resources, you probably need an assignment operator too. See the Rule of Three: http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29
But the best solution is to stop using raw pointers. Use a smart pointer and this problem will not occur in the first place, and you can omit your destructor.
In a situation like this, writing your own copy constructor, assignment operator and destructor should be your last resort, not your first reaction.
Your first reaction should usually be to use some pre-defined class that already handles these chores for you. In this case, changing from a raw pointer to a shared_ptr (for only one possibility) cleans up the code fairly quickly. Using it, the code ends up something like this:
#include <iostream>
#include <memory>
using namespace std;
class Line
{
public:
int getLength();
Line( int len ); // simple constructor
~Line(); // destructor
// copy constructor removed, because the one supplied by the
// compiler will be fine. Likewise the compiler-generated assignment
// operator.
private:
shared_ptr<int> ptr;
};
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
// Note the use of make_shared instead of a raw `new`
ptr = make_shared<int>(len);
}
Line::~Line(void)
{
cout << "Freeing memory!" << endl;
// don't need to actually do anything--freeing is automatic
}
int Line::getLength()
{
return *ptr;
}
void display(Line obj)
{
cout << "Length of line : " << obj.getLength() <<endl;
}
// Main function for the program
int main()
{
Line line1(199);
Line line2(1);
line2 = line1; // uses compiler-generated assignment operator (which works)
cout << line1.getLength() << " " << line2.getLength() << endl ;
display(line1);
display(line2);
cin.get();
return 0;
}
Depending upon the situation, a unique_ptr might be a better fit than a shared_ptr. In this case, shared_ptr is probably easier to incorporate into the existing code though.
You might also want to read R. Martinho Fernandes' Rule of Zero blog post on this subject.
If no user-defined copy assignment operators are provided for a class type (struct, class, or union), the compiler will always declare one as an inline public member of the class.
This implicitly-declared copy assignment operator has the form T& T::operator=(const T&) if all of the following is true:
Each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B&
Each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M&
Otherwise the implicitly-declared copy assignment operator is declared as T& T::operator=(T&). (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument)
Copied from this article from CPPReference.
The following "minimal" example should show the use of rule of 3 (and a half).
#include <algorithm>
#include <iostream>
class C
{
std::string* str;
public:
C()
: str(new std::string("default constructed"))
{
std::cout << "std ctor called" << std::endl;
}
C(std::string* _str)
: str(_str)
{
std::cout << "string ctor called, "
<< "address:" << str << std::endl;
}
// copy ctor: does a hard copy of the string
C(const C& other)
: str(new std::string(*(other.str)))
{
std::cout << "copy ctor called" << std::endl;
}
friend void swap(C& c1, C& c2) {
using std::swap;
swap(c1.str, c2.str);
}
const C& operator=(C src) // rule of 3.5
{
using std::swap;
swap(*this, src);
std::cout << "operator= called" << std::endl;
return *this;
}
C get_new() {
return C(str);
}
void print_address() { std::cout << str << std::endl; }
};
int main()
{
C a, b;
a = b.get_new();
a.print_address();
return 0;
}
Compiled it like this (g++ version: 4.7.1):
g++ -Wall test.cpp -o test
Now, what should happen? I assumed that the line a = b.get_new(); would make a hard copy, i.e. allocate a new string. Reason: The operator=() takes its argument, as typical in this design pattern, per value, which invokes a copy ctor, which will make a deep copy. What really happened?
std ctor called
std ctor called
string ctor called, address:0x433d0b0
operator= called
0x433d0b0
The copy ctor was never being called, and thus, the copy was soft - both pointers were equal. Why is the copy ctor not being called?
The copies are being elided.
There's no copy because b.get_new(); is constructing its 'temporary' C object exactly in the location that ends up being the parameter for operator=. The compiler is able to manage this because everything is in a single translation unit so it has sufficient information to do such transformations.
You can eliminate construction elision in clang and gcc with the flag -fno-elide-constructors, and then the output will be like:
std ctor called
std ctor called
string ctor called, address:0x1b42070
copy ctor called
copy ctor called
operator= called
0x1b420f0
The first copy is eliminated by the Return Value Optimization. With RVO the function constructs the object that is eventually returned directly into the location where the return value should go.
I'm not sure that there's a special name for elision of the second copy. That's the copy from the return value of get_new() into the parameter for operator= ().
As I said before, eliding both copies together results in get_new() constructing its object directly into the space for the parameter to operator= ().
Note that both pointers being equal, as in:
std ctor called
std ctor called
string ctor called, address:0xc340d0
operator= called
0xc340d0
does not itself indicate an error, and this will not cause a double free; Because the copy was elided, there isn't an additional copy of that object retaining ownership over the allocated string, so there won't be an additional free.
However your code does contain an error unrelated to the rule of three: get_new() is passing a pointer to the object's own str member, and the explicit object it creates (at the line "string ctor called, address:0xc340d0" in the output) is taking ownership of the str object already managed by the original object (b). This means that b and the object created inside get_new() are both attempting to manage the same string and that will result in a double free (if the destructor were implemented).
To see this change the default constructor to display the str it creates:
C()
: str(new std::string("default constructed"))
{
std::cout << "std ctor called. Address: " << str << std::endl;
}
And now the output will be like:
std ctor called. Address: 0x1cdf010
std ctor called. Address: 0x1cdf070
string ctor called, address:0x1cdf070
operator= called
0x1cdf070
So there's no problem with the last two pointers printed being the same. The problem is with the second and third pointers being printed. Fixing get_new():
C get_new() {
return C(new std::string(*str));
}
changes the output to:
std ctor called. Address: 0xec3010
std ctor called. Address: 0xec3070
string ctor called, address:0xec30d0
operator= called
0xec30d0
and solves any potential problem with double frees.
C++ is allowed to optimize away copy construction in functions that are returning a class instance.
What happens in get_new is that the object freshly constructed from _str member is returned directly and it's then used as the source for the assignment. This is called "Return Value Optimization" (RVO).
Note that while the compiler is free to optimize away a copy construction still it's required to check that copy construction can be legally called. If for example instead of a member function you have a non-friend function returning and instance and the copy constructor is private then you would get a compiler error even if after making the function accessible the copy could end up optimized away.
It isn't exactly clear why you expect the copy ctor to be used. The get_new() function will not create a new copy of the C object when it returns the value. This is an optimization called Return Value Optimization, any C++ compiler implements it.
I am confused over the differences between passing objects by reference and by value to functions of a particular class. If I pass objects by value, I know that the default copy constructor makes a member-by-member copy of the the object for use in the given function. However, if I am passing objects as a const reference for a class that requires deep copy, is the copy constructor still called? Say that I had a function
void debug(const MyClass& object1);
Would passing object1 call the copy constructor? Or is the object passed into the function directly without having a copy made? One more question - If I have a class called Fraction-
Fraction A(1,2); // 1 is this numerator, 2 the denominator
A = Fraction(2,3);
Does the aforementioned line call the default constructor to make a temporary object Fraction(2,3) and then the assignment operator?
Thanks.
Would passing object1 call the copy constructor?
No, it will not call the copy constructor since passed by reference
No copy is made in this case
A = Fraction(2,3);
Yes, it will call the constructor with two parameters (or default constructor if both parameters have default values), then call the copy assignment operator.
You can see the output from code below:
#include <iostream>
using namespace std;
class Fraction
{
public:
int denom;
int nominator;
Fraction(int d , int n ):denom(d), nominator(n)
{
cout << "call non-copy constructor" <<endl;
}
Fraction(const Fraction& rhs)
{
cout << "call copy constructor" <<endl;
denom = rhs.denom;
nominator = rhs.nominator;
}
const Fraction& operator=(const Fraction& rhs)
{
cout << "call copy assignment operator" << endl;
if (this == &rhs)
{
return *this;
}
denom = rhs.denom;
nominator = rhs.nominator;
return *this;
}
};
void debug(const Fraction& obj)
{
cout << "this is debug: pass by reference " <<endl;
}
void debugPassByValue(Fraction obj)
{
cout << "this is debug: pass by value" <<endl;
}
int main()
{
Fraction A(1,2);
cout << "--------------" <<endl;
debug(A);
cout << "--------------" <<endl;
A = Fraction(2,3);
cout << "--------------" <<endl;
debugPassByValue(A);
cout << "--------------" <<endl;
cin.get();
return 0;
}
You will see the following output:
call non-copy constructor //Fraction A(1,2);
--------------
this is debug: pass by reference //debug(A);
--------------
call non-copy constructor //A = Fraction(2,3);---> construct temporary object
call copy assignment operator //A = Fraction(2,3);
--------------
call copy constructor //debugPassByValue(A);
this is debug: pass by value
--------------
Now you will have a clearer view of what are called.
In the following we will consider [x] to mean that x is optional.
I am confused over the differences between passing objects by reference and by value to functions of a particular class.
When you pass an object by value, the program must create the local object of the function therefore it calls the copy constructor of the class to create this object. When you pass by reference (and seemingly by pointer) the variable object1 inside the function is just an alias of the object you passed to the function; therefore if you edit the one inside the function, the edits will be applied to the outside object as well.
Does the aforementioned line call the default constructor to make a temporary object Fraction(2,3) and then the assignment operator?
It's the assignment operator. Considering A to be an already declared variable of type X it will be called X Fraction::operator=([const] Fraction[&]) or any compatible type.
Notice: when declaring Fraction x = Fraction(2, 3) it won't be used the operator= as you may expect, the corresponding constructor will be called instead (in this case Fraction::Fraction([const] Fraction[&])).
Indeed in the case of debug no copy is made.
In the second case, I'm not quite sure I understand your question. This line:
A = Fraction(2,3);
Should use Fraction's assignment operator. A already exists, so it uses the assignment operator on instance A to assign it Fraction(2,3) which is a temporary object.
I do not understand how this code is compiling. Can somebody please explain what is going on in there.
#include <iostream>
using namespace std;
class B
{
public:
B(const char* str = "\0") //default constructor
{
cout << "Constructor called" << endl;
}
B(const B &b) //copy constructor
{
cout << "Copy constructor called" << endl;
}
};
int main()
{
B ob = "copy me"; //why no compilation error.
return 0;
}
The optput is:
Constructor called
P.S.: I could not think of a more apt title than this, Anyone who can think of a better title, please modify it.
The type of "copy me" is char const[8], which decays to char const *. Since the default constructor is not explicit, "copy me" can be implicitly converted to B, and thus ob can be copy-constructed from that implicitly converted, temporary B-object.
Had the default constructor been declared explicit, you would have had to write one of the following:
B ob1 = B("copy me");
B ob2("copy me");
Had the copy constructor also been declared explicit, you would have had to say one of these:
B ob3(B("copy me"));
B ob4("copy me");
In practice, all copies will be elided by any half-decent compiler, and you always end up with a single default constructor invocation.
Because this
B ob = "copy me";
invokes the copy constructor, which takes argument const B &b and you class B has a constructor
B(const char* str = "\0")
which is not defined as explicit.
The compiler is allowed to make one implicit conversion.
So, what happens here:
B ob = "copy me";
is:
Create a temp, unnamed object B, using the provided const char* str - this is allowed, since class B has constructor, which takes one argument and is not defined as explicit. In other words, all objects with type B can be constructed from a const char*
Create the object ob, using the temp object, created in 1..
If you add keyword explicit to your default constructor to prevent implicit conversion. Then it will not compile. Your answer is implicit conversion.
That's because of implicit conversion of the assignment statement to
B ob("copy me");
Try this to fail compilation (look at the explicit keyword):
#include <iostream>
using namespace std;
class B
{
public:
explicit B(const char* str = "\0") //default constructor
{
cout << "Constructor called" << endl;
}
B(const B &b) //copy constructor
{
cout << "Copy constructor called" << endl;
}
};
int main()
{
B ob = "copy me"; //why no compilation error.
return 0;
}
[it shouldn't compile because] the specified line does not match in data types
There is no compilation error because there exists a constructor of B that takes const char* as an argument, allowing for conversion between const char* and B.
This is because of implicit conversion. Add a Explicit to your Default constructor and try. it will Fail to compile.
Edit: after discussion with Kerrek SB I got a copy of the C++11 standard. I was wrong, there's a temporary. I'm editing this reply to reflect my newly acquired understanding.
15 years ago I knew C++ extremely well (that was around the time the first standard was to be released). I haven't used it since late 1998 so I have forgotten a lot and I know almost nothing of the recent standards.
The code is correct.
B ob = "copy me"; //why no compilation error.
There's no error. This is parsed as a declaration of an initialized variable. B is the type, ob the name of the variable, "copy me" the initializer.
The initializer is of type const char* and there is, in class B, a constructor that takes a const char* typed single argument. That constructor is not declared restricted by explicit and therefore can be used in this context.
Either a temporary object is created and then copied (you see both lines printed out) or the copy is elided and only the conversion constructor is called to construct directly at the destination (you see only one line printed). The standard explicitly allows this even if the copy constructor has side effects.
The program execution will print Constructor called to stdout. It may or may not then also print Copy constructor called. There is no error.