Copy Constructor Undefined Call - c++

This is the full example (source book: C++ From Ground Up, 3rd Edition, page 219-320):
class sample {
char *s;
public:
sample(); // normal constructor
sample(const sample &ob); // copy constructor
~sample( ) { cout << "s: " << s <<" ,Freeing s\n"; if(s) delete [] s;}
void show() { cout << s << "\n"; }
void set(char *str);
sample operator=(const sample &ob); // overload assignment
};
// Normal constructor.
sample::sample() {
s = new char('\0'); // s points to a null string.
cout << "Normal constructor: s: " << strlen(s) << endl;
}
// Copy constructor.
sample::sample(const sample &ob) {
cout << "Copy constructor: ob.s: "<< ob.s << " ,strlen(ob.s): " << strlen(ob.s) << "\n";
s = new char[strlen(ob.s)+1];
strcpy(s, ob.s);
}
// Load a string.
void sample::set(char *str) {
s = new char[strlen(str)+1];
strcpy(s, str);
}
// Overload assignment operator.
sample sample::operator=(const sample &ob) {
/* If the target memory is not large enough
then allocate new memory. */
cout << "operator= strlen(ob.s): " << strlen(ob.s) << " ,strlen(s): " << strlen(s) << endl;
if(strlen(ob.s) > strlen(s)) {
cout << "operator= Larger memory of target object. Deleting current...\n";
delete [] s;
s = new char[strlen(ob.s)+1];
}
strcpy(s, ob.s);
return *this;
}
// Return an object of type sample.
sample input() {
char instr[80];
static sample str;
cout << "Enter a string: ";
cin >> instr;
str.set(instr);
return str;
}
int main() {
sample ob;
// assign returned object to ob
ob=input(); // This is now OK
ob.show();
return 0;
}
However I do not get why TWO times copy constructor is called.
(output once code is ran)
Normal constructor: s:
Normal constructor: s:
Enter a string: Hello
Copy constructor: ob.s: Hello ,strlen(ob.s): 5
operator= strlen(ob.s): 5 strlen(s): 0
operator= Larger memory of target object. Deleting current...
Copy constructor: ob.s: Hello ,strlen(ob.s): 5
s: Hello, Freeing s
s: Hello, Freeing s
Hello
s: Hello, Freeing s
s: Hello, Freeing s
I know it is called when input() function returns, and create temporary object (by calling copy constructor), but I do not get why second time since, as much as I know (but maybe I am wrong) copy constructors are NOT called for assignment operations, but it looks like, despite of that, when return *this; is called (when overloaded operator returns value), copy constructor is called?
What did I missed?
Thankx

The code is really terrible. Not to mention other bugs, here is why copy constructor is called twice.
First time it's called when an object is returned from input() since it's static and returned by value, so no RVO can be applied.
The second call happens as a result of return *this; in operator=() because for some reason it's returning an object also by value:
sample operator=(const sample &ob);
// ^^^

Related

Does conversion constructor create an object and destroys it if there is no assignment operator in c++?

I have a somehow basic question regarding the conversion constructors and assignment operators. I can't find a similar question but maybe I am searching wrongly.
Anyway.. I had made a class like this
class String
{
private:
// enum { SZ = 80 };
static const int SZ = 80;
char str[SZ]; //array
public:
String() //constructor, no args
{
cout << "Default constructor called, p_str = " << (void*)str << endl;
strcpy(str, "");
}
String( char s[] ) //constructor, one arg
{
cout << "Copy constructor called, p_str = " << (void*)str << endl;
strcpy(str, s);
}
void display() //display string
{
cout << str << endl;
// cout << "str ptr = " << (void*)str << endl;
}
void concat(String s2) //add arg string to
{ //this string
if( strlen(str)+strlen(s2.str) < SZ )
strcat(str, s2.str);
else
cout << "\nString too long";
}
void SetString(char* strToSet)
{
strcpy(str, strToSet);
}
// void operator =(const char* strCpy)
// {
// cout << "Copy assignemnt called..." << endl;
// strcpy(str, strCpy);
// }
~String()
{
cout << "Destructor called..." << endl;
}
void* GetStrPtr()
{
return (void*)str;
}
};
and in the main:
String myStr1 = "Hello Hello";
void* old_str_ptr = myStr1.GetStrPtr();
cout << "old_str_ptr = " <<old_str_ptr << endl;
myStr1 = "hello World!!";
cout << "old_str_ptr = " <<old_str_ptr << endl;
void* new_str_ptr = myStr1.GetStrPtr();
cout << "new_str_ptr = " <<new_str_ptr << endl;
myStr1.display();
cout << (char*)old_str_ptr << endl;
cout << (char*)new_str_ptr << endl;
This is the output I got:
Copy constructor called, p_str = 0x62fdd8
old_str_ptr = 0x62fdd8
Copy constructor called, p_str = 0x62fe28
Destructor called...
old_str_ptr = 0x62fdd8
new_str_ptr = 0x62fdd8
hello World!!
hello World!!
hello World!!
Destructor called...
Can someone explains what happens exactly at this line in main:
myStr1 = "hello World!!"
As I can see that it calls the conversion constructor (as the assignment operator is commented) and the address of "str" array is changed then what I don't understand is that the destructor is called and the address is returned back as seen in the output.
In myStr1 = "hello World!!"; the two types are not compatible, so assigment would normally not be possible. However, the compiler notices that you have an implicit conversion constructor that accepts a pointer-to-char and so it invokes this constructor to create a temporary object from which assignment can happen. This is the sequence of events:
A temporary String object is constructed, invoking String("hello World!"").
The temporary is either copy-assigned (C++ < 11) or move-assigned (C++ >= 11) to myStr1 (you don't overload assignment so you don't observe this step in your output). Whether copy-assigned or move-assigned, the relevant compiler-generated assignment operator performs a simple memberwise value copy in this case since the members can't be moved.
The temporary is destructed.
The location of str does not change simply because it can't: it's an array member of the class, meaning its storage is directly allocated as part of String objects. str evaluated as a pointer points to a region of memory within the String object.
The implicit move-assignment operator simply copies the contents of the source object's str array into the target object's str array.
You see a different value on the second constructor message because this is a different object being constructed, and therefore its str member exists in a different memory location. However, this object is destructed after its value is copied into the myStr1 object.

how to return object without create copy of that?

I develop simple c++ class to testing when c++ objects destroy; now I have a problem, when an object return by function, c++ create a new object and return that and when return reference destroy object what is my mistake ?
simple class attached below.
#include <iostream>
using namespace std;
static int freeCounter=0;
class TestCopy {
private:
string pStr;
public:
TestCopy(const TestCopy &obj){
pStr=obj.pStr;
}
TestCopy(string &test){
pStr=test;
}
~TestCopy(){ freeCounter++; cout << freeCounter <<"\t" << pStr << endl; }
TestCopy get(){
TestCopy x=*this;
return TestCopy(x); // -> TestCopy(x) is first destroy in result
}
string getStr(){
return pStr;
}
};
int main(){
string xstr="test";
TestCopy x(xstr); // x is third destroy
TestCopy x2=x.get(); // x2 is second destroy
cout << x.getStr() << endl;
return 0;
}
and result
1 test
test
2 test
3 test
x in function get is a local object, when the function finishes, x will be destroyed.
so, x is the first destroyed.
First a review of OP's code. I've modified it slightly to make what's going on more obvious.
#include <iostream>
using namespace std;
static int allocCounter = 0;
class TestCopy
{
private:
string pStr;
int counter;
public:
TestCopy(const TestCopy &obj)
{
allocCounter++;
counter = allocCounter;
cout << "copy construct " << counter << endl;
pStr = obj.pStr;
}
TestCopy(const string &test)
{
allocCounter++;
counter = allocCounter;
cout << "string construct " << counter << endl;
pStr = test;
}
~TestCopy()
{
cout << counter << "\t" << pStr << endl;
}
TestCopy get()
{
TestCopy x = *this; // copy constructed
return TestCopy(x); // copy constructed and copy elision
}
string getStr()
{
return pStr;
}
TestCopy & operator=(const TestCopy &obj)
{
cout << "assigned " << obj.counter << " to "<< counter << endl;
pStr = obj.pStr;
// counter = obj.counter; deliberately left out
return *this;
}
};
int main()
{
string xstr = "test";
TestCopy x(xstr); // string constructed
TestCopy x2 = x.get(); // Would be a copy constructed if not for copy elision
return 0;
}
Output
string construct 1
copy construct 2
copy construct 3
2 test
3 test
1 test
Note no calls to the assignment operator even with TestCopy x=*this;
Alright. Now how do we chop some of this down?
First we get rid of a redundant copy in get
TestCopy get()
{
return *this; // copy constructed. Or is it? The copy construction could
// happen at the caller. Either way it is copied and elided
}
Output
string construct 1
copy construct 2
2 test
1 test
So at this point we know there is no need to copy or assign in get because the return statement will do it for us. This is the important part with respect to OP's question.
But if we change main a bit and add an assignment operator we can observe a bit more interesting behaviour.
int main()
{
string xstr = "test";
TestCopy x(xstr); // string constructed
TestCopy x2(""); //string constructed
x2 = x.get(); // assigned and a copy construct when returning from get
cout << "done main" << endl;
return 0;
}
Output
string construct 1
string construct 2
copy construct 3
assigned 3 to 2
3 test
done main
2 test
1 test
The return from get was assigned to x2, then destroyed. x2 gets destroyed and finally x.
thank you #seaman with your help I found my mistake.
by changing
TestCopy x=*this;
with
const TestCopy &x=*this;
problem solved

Reference Parameters Address Automatically NOT passed

I have the following issue with reference parameters:
When we have a function with reference parameters, the compiler will automatically pass to that function, the address of any argument it is called with.
Example (with object):
class sample {
char *s;
public:
sample(); // normal constructor
sample(const sample &ob); // copy constructor
~sample( ) { if(s) delete [] s; cout << "Freeing s\n"; }
void show() { cout << s << "\n"; }
void set(char *str);
};// Definition will be excluded from here`
and we have a function with reference parameters of this class instance,
like:
void funtionWithRef(sample &kk); // declaration
void funtionWithRef(sample &sam){ // definition
sam.show();
}
and one function with return object of type sample:
sample functionReturnSample(); //declaration
sample functionReturnSample(){ // definition
sample sam;
sam.set("test sample");
return sam;
}
Now, when we do:
int main() {
sample temp = functionReturnSample();
funtionWithRef(temp);
return 0;
}
It works perfect. When we put temp object as an argument to funtionWithRef, compiler pass address of that object to the function.
But WHY it does not work, if we do NOT first assign a returning value of functionReturnSample to the instance, but directly put that method as an argument like :
funtionWithRef(functionReturnSample());
Why is this different, when we are doing the same thing, and according to some books I consulted, whit SHOULD
EDIT
#user657267
This is the full example (source book: C++ From Ground Up, 3rd Edition, page 219-320):
class sample {
char *s;
public:
sample(); // normal constructor
sample(const sample &ob); // copy constructor
~sample( ) { cout << "s: " << s <<" ,Freeing s\n"; if(s) delete [] s;}
void show() { cout << s << "\n"; }
void set(char *str);
sample operator=(sample &ob); // overload assignment
};
// Normal constructor.
sample::sample() {
s = new char('\0'); // s points to a null string.
cout << "Normal constructor: s: " << strlen(s) << endl;
}
// Copy constructor.
sample::sample(const sample &ob) {
cout << "Copy constructor: ob.s: "<< ob.s << " ,strlen(ob.s): " << strlen(ob.s) << "\n";
s = new char[strlen(ob.s)+1];
strcpy(s, ob.s);
}
// Load a string.
void sample::set(char *str) {
s = new char[strlen(str)+1];
strcpy(s, str);
}
// Overload assignment operator.
sample sample::operator=(sample &ob) {
/* If the target memory is not large enough
then allocate new memory. */
cout << "operator= strlen(ob.s): " << strlen(ob.s) << " ,strlen(s): " << strlen(s) << endl;
if(strlen(ob.s) > strlen(s)) {
cout << "operator= Larger memory of target object. Deleting current...\n";
delete [] s;
s = new char[strlen(ob.s)+1];
}
strcpy(s, ob.s);
return *this;
}
// Return an object of type sample.
sample input() {
char instr[80];
static sample str;
cout << "Enter a string: ";
cin >> instr;
str.set(instr);
return str;
}
int main() {
sample ob;
// assign returned object to ob
ob=input(); // This is now OK
ob.show();
return 0;
}
This wont compile, and reports error:
**error: no match for ‘operator=’ (operand types are ‘sample’ and ‘sample’)**
So it is copy/past of the code from the mentioned book. You can check please.
However I figureout if I specify overloaded = operator arguments to be const like:
sample operator=(const sample &ob); // overload assignment
Then it DOES work.
However, what is bothering me is, now when I have runnable code, I do not get why TWO times copy constructor is called.
I know it is called when input() function returns, and create temporary object, but I do not get why second time since, as much as I know (but maybe I am wrong) copy constructors are NOT called for assignment operations (same Book, pages 291-292), but it looks like, despite of that, when return *this; is called (when overloaded operator returns value), copy constructor is called?
So what is about that ?
Thankx

Crash Issue - C++ Code Design using pointers and destructors

I have a question regarding the following code, which crashes. I am creating a local variable in testfunction() and then pushing it (variable "y") into a list. This variable has a member pointer "b" of object type Ball. As I understand, this local variable "y" is on the stack, so its' destructor will be called after testfunction() is completed. Also, as I understand, a vector "copies" an object into its' list. From what I've learned, it is best practice to delete a pointer in the destructor if one exists in its' class. So, there is "delete b" in the destructor of Example.
The issue that I am having is that the object y.b is being destroyed at the completion of testfunction(). In main(), I am able to see the value of "name" and the address of "b", but the object "b" has already been deleted. I would like to avoid this.
I think there is an issue with the design of the code/use of pointers vs references, etc. Please guide me in the right direction, I am an idiot!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Ball
{
public:
int a;
Ball()
{
a = 0;
}
~Ball()
{
cout << "destroyed Ball()" << endl;
}
};
class Example
{
public:
string name;
Ball* b;
Example()
{
name = "";
b = NULL;
}
~Example()
{
cout << "destroying Example()" << endl;
delete b;
}
};
void testfunction(vector<Example>& list)
{
cout << "entered testfunction1()" << endl;
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
cout << "y.b->a = " << y.b->a << endl;
list.push_back(y);
cout << "exit testfunction1()" << endl;
}
void testfunction2()
{
cout << "entered testfunction2()" << endl;
Example* y = new Example();
cout << "exit testfunction2()" << endl;
}
int main() {
vector<Example> list;
testfunction(list);
//testfunction2();
if(list[0].b == NULL)
cout << "b is null" << endl;
else
cout << "b is not null" << endl;
cout << list[0].name << endl;
cout << list[0].b << endl;
cout << "list[0].b->a = " << list[0].b->a << endl;
return 0;
}
Since class Example has a pointer member and it tries to own a dynamically allocated resource, it needs non-default copy operations, in other words, it needs user-defined copy constructor and assignment operator.
Inside testfunction, when you copy y into vector, both local y and y copied to the vector point to very same Ball object. The local y is destroyed at the end of the function and Ball is deleted. However, that deleted Ball still pointed by the y in vector
void testfunction(vector<Example>& list)
{
// ...
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
list.push_back(y);
// ...
} // <-- destructor for Example y is called and y.b is deleted
Define a copy constructor and an assignement operator for your class Example.
These shall copy properly your object (creating a duplicated Ball object) when pushed back on the vector.
Example(const Example& a)
{
name = a.name; // attention no dynamic allocation
cout << "copy" <<endl;
if (a.b) {
b = new Ball(*a.b); // create a new duplicated Ball
}
else b = NULL;
}
The problem in your example is that the default copy constructor is called when you pushback the object. It copies memberwise and so the pointer to Ball is copied, not the object pointed to.
Yet another alternative could be to replace your Ball* with shared_ptr<Ball> (and accordingly, new Ball with make_shared<Ball>() and the delete b of the object with a b.reset()). The principle is that this smart pointer keeps track of the number of time the object pointed to is used, so that it will not delete it twice, but only when its no longer used anywhere.

How is this code running?

Here is the code first, it comes from 'Ruminations on C++' chapter 10
// TestCode.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
class P_Node
{
friend class Picture;
protected:
P_Node() : use(1)
{
}
virtual ~P_Node()
{
}
private:
int use;
};
class Picture
{
friend Picture frame(const Picture&);
public:
Picture() : p(new P_Node)
{
cout << "Constructor\t" << "Picture::Picture()" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
}
Picture(const Picture& orig) : p(orig.p)
{
cout << "Copy Constructor\t" << "Picture::Picture(const Picture&)" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
orig.p->use++;
}
~Picture()
{
cout << "Destructor\t" << "Picture::~Picture()" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
cout << "Deleted" << endl;
delete p;
}
}
Picture& operator=(const Picture& orig)
{
cout << "operator=\t" << "Picture& Picture::operator=(const Picture& orig)" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
orig.p->use++;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
delete p;
}
p = orig.p;
return *this;
}
private:
Picture(P_Node* p_node) : p(p_node)
{
// Why not p_node->use++?
cout << "Picture::Picture(P_Node* p_node)\tcalled" << endl;
}
P_Node *p;
};
class Frame_Pic : public P_Node
{
friend Picture frame(const Picture&);
private:
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
Picture p;
};
Picture frame(const Picture& pic)
{
return new Frame_Pic(pic);
}
int main(int argc, char* argv[])
{
Picture my_pic;
frame(my_pic);
return 0;
}
The result is:
Constructor Picture::Picture() called
Picture p count 1
Copy Constructor Picture::Picture(const Picture&) called
Picture p count 1
Frame_Pic::Frame_Pic(const Picture& orig) called
Picture::Picture(P_Node* p_node) called
Destructor Picture::~Picture() called
Picture p count before decrease 1
Picture p count after decrease 0
Deleted
Destructor Picture::~Picture() called
Picture p count before decrease 2
Destructor Picture::~Picture() called
Picture p count before decrease 1
Picture p count after decrease 0
Deleted
I have two questions about this code:
Why is the copy constructor called before Frame_Pic's Constructor? In my mind, the copy constructor is called because frame(my_pic) is returning a Picture by value. But that should be called after Frame_Pic's Constructor.
In Picture::Picture(P_Node* p_node), why not increase the use count? isn't this creating a new Picture?
Thanks for any help.
I'm using VC6 under Windows XP.
1, Why is the Copy Constructor called before Frame_Pic's Constructor?
Because the p member is being copy-constructed in the initialization list of Frame_pic's constructor. The initialization list runs before the constructor's body is entered.
In my mind, the Copy Constructor is called because frame(my_pic) is returning a Picture by value. But that should be called after Frame_Pic's Constructor.
frame() is declared to return a Picture instance by value, but it is coded to return a Frame_pic* instead. Frame_pic derives from P_node, and Picture has a constructor that accepts a P_node*, and that constructor is accessible to frame() so the compiler allows it.
2, In Picture::Picture(P_Node* p_node), why not increase the use count? isn't this creating a new Picture?
The use count is on P_node, not Picture. The Picture that frame() returns owns the Frame_pic that frame() creates, whose use count member is already 1 by the Frame_pic constructor. That is why that Picture constructor does not increment the use count - it is already at the correct value.
The Frame_pic contains its own Picture that is copy-constructed from another Picture, so that Picture constructor needs to increment the use count of the original Picture.
The copy constructor is invoked by Frame_Pic's constructor (it's invoked by the initializer : p(pic)). However Frame_Pic's constructor doesn't print until after all initializers have been run.
Because the intended use of the constructor is not documented, it's hard to say. It may be a bug, or it may be 'attach semantics' - that is, it may be considering the case where you take manual control of the P_Node*, then later give it back. However attach semantics is unlikely, as there's no corresponding detach mechanism to return the pointer and clear it without decrementing the refcount. So, most likely a bug.
Note that while this sort of manual reference counting can be good as a learning exercise, modern C++ code generally uses smart pointers (eg, std::shared_ptr or boost::shared_ptr, invasive_ptr, etc) to automate the process.
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
You initializing 'p' using its copy constructor 'p(pic)', hence it gets called in the order you see