473,395 Members | 1,677 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

destructor invoked without constructor.

Hi Everyone,

I have the following unit to explain the problem that i have,

class sample
{
public : sample()
{
printf("in sample...\n");
}
~sample()
{
printf("out sample...\n");
}
void invoke(sample obj)
{
printf("in invoke...\n");
}
};

int main()

{

sample obj;
sample obj1;
obj1.invoke(obj);
printf("...end...\n");
return 0;

}
The following is the output,

in sample...
in sample...
in invoke...
out sample...
....end...
out sample...
out sample...

i think the first "out sample..." is for the object obj passed by
value, which indicates that a new temp object has been destroyed,
which means that it should have been created, if so, shouldn't the "in
sample" have been printed once more before "in invoke"...?

May 4 '07 #1
13 2353
On 4 Maj, 11:03, sam_...@yahoo.co.in wrote:
Hi Everyone,

I have the following unit to explain the problem that i have,

class sample
{
public : sample()
{
printf("in sample...\n");
}
~sample()
{
printf("out sample...\n");
}
void invoke(sample obj)
{
printf("in invoke...\n");
}
};

int main()

{

sample obj;
sample obj1;
obj1.invoke(obj);
printf("...end...\n");
return 0;

}

The following is the output,

in sample...
in sample...
in invoke...
out sample...
...end...
out sample...
out sample...

i think the first "out sample..." is for the object obj passed by
value, which indicates that a new temp object has been destroyed,
which means that it should have been created, if so, shouldn't the "in
sample" have been printed once more before "in invoke"...?
It is created, but using the copy-constructor, which you have not
implemented so the compiler-generated one is used, and that one does
not print anything. Add

sample(const sample&) { std::cout << "copy\n"; }

to your class and see what happens.

--
Erik Wikström

May 4 '07 #2
<sa*****@yahoo.co.inwrote in message
news:11**********************@l77g2000hsb.googlegr oups.com...
Hi Everyone,

I have the following unit to explain the problem that i have,

class sample
{
public : sample()
{
printf("in sample...\n");
}
~sample()
{
printf("out sample...\n");
}
void invoke(sample obj)
{
printf("in invoke...\n");
}
};

int main()

{

sample obj;
sample obj1;
obj1.invoke(obj);
printf("...end...\n");
return 0;

}
The following is the output,

in sample...
in sample...
in invoke...
out sample...
...end...
out sample...
out sample...

i think the first "out sample..." is for the object obj passed by
value, which indicates that a new temp object has been destroyed,
which means that it should have been created, if so, shouldn't the "in
sample" have been printed once more before "in invoke"...?
No. The temporary is created using the copy constructor, and since you
didn't supply any it was automatically generated (and obviously not with the
printf statement in it). Add the following constructor and it should work as
you expect:

sample(const sample & s)
{
printf("in sample... (copy ctor)\n");
}

Btw, it might be handy to output the this pointer as well so you can exactly
see what ctor-dtor pairs belong to eachother :)

- Sylvester
May 4 '07 #3
On May 4, 2:03 pm, sam_...@yahoo.co.in wrote:
Hi Everyone,

I have the following unit to explain the problem that i have,

class sample
{
public : sample()
{
printf("in sample...\n");
}
~sample()
{
printf("out sample...\n");
}
void invoke(sample obj)
{
printf("in invoke...\n");
}
};

int main()

{

sample obj;
sample obj1;
obj1.invoke(obj);
printf("...end...\n");
return 0;

}

The following is the output,

in sample...
in sample...
in invoke...
out sample...
...end...
out sample...
out sample...

i think the first "out sample..." is for the object obj passed by
value, which indicates that a new temp object has been destroyed,
which means that it should have been created, if so, shouldn't the "in
sample" have been printed once more before "in invoke"...?
Invoking a function with pass by value argument would definitely call
copy constructor, whereas pass the argument by reference wouldn't
create an object.
So If you would've defined a copy constructor for the class sample,
within which a print statement your doubt would've got cleared.

I hope this helps.

-
Sukumar R

May 4 '07 #4
On May 4, 2:21 pm, WittyGuy <wittyguys...@gmail.comwrote:
On May 4, 2:03 pm, sam_...@yahoo.co.in wrote:


Hi Everyone,
I have the following unit to explain the problem that i have,
class sample
{
public : sample()
{
printf("in sample...\n");
}
~sample()
{
printf("out sample...\n");
}
void invoke(sample obj)
{
printf("in invoke...\n");
}
};
int main()
{
sample obj;
sample obj1;
obj1.invoke(obj);
printf("...end...\n");
return 0;
}
The following is the output,
in sample...
in sample...
in invoke...
out sample...
...end...
out sample...
out sample...
i think the first "out sample..." is for the object obj passed by
value, which indicates that a new temp object has been destroyed,
which means that it should have been created, if so, shouldn't the "in
sample" have been printed once more before "in invoke"...?

Invoking a function with pass by value argument would definitely call
copy constructor, whereas pass the argument by reference wouldn't
create an object.
So If you would've defined a copy constructor for the class sample,
within which a print statement your doubt would've got cleared.

I hope this helps.

-
Sukumar R- Hide quoted text -

- Show quoted text -
So it is correct to understand that the default copy constructor would
be invoked in all calls to member functions where the object of the
same class's type is passed by value?
....

Thanks in advance!!!

May 4 '07 #5
On May 4, 2:14 pm, Erik Wikström <eri...@student.chalmers.sewrote:
On 4 Maj, 11:03, sam_...@yahoo.co.in wrote:


Hi Everyone,
I have the following unit to explain the problem that i have,
class sample
{
public : sample()
{
printf("in sample...\n");
}
~sample()
{
printf("out sample...\n");
}
void invoke(sample obj)
{
printf("in invoke...\n");
}
};
int main()
{
sample obj;
sample obj1;
obj1.invoke(obj);
printf("...end...\n");
return 0;
}
The following is the output,
in sample...
in sample...
in invoke...
out sample...
...end...
out sample...
out sample...
i think the first "out sample..." is for the object obj passed by
value, which indicates that a new temp object has been destroyed,
which means that it should have been created, if so, shouldn't the "in
sample" have been printed once more before "in invoke"...?

It is created, but using the copy-constructor, which you have not
implemented so the compiler-generated one is used, and that one does
not print anything. Add

sample(const sample&) { std::cout << "copy\n"; }

to your class and see what happens.

--
Erik Wikström- Hide quoted text -

- Show quoted text -
And what is the reason that only copy constructor is invoked in this
case and why not the regular constructor?

May 4 '07 #6
sa*****@yahoo.co.in wrote:
....
So it is correct to understand that the default copy constructor would
be invoked in all calls to member functions where the object of the
same class's type is passed by value?
Remove the word "default" and then you are correct.

The compiler provides a "default" copy constructor (if one is needed).
The programmer can provide a copy constructor, in which case the
compiler does not create a "default" one. Either way, if you pass by
value, the copy constructor is invoked.
May 4 '07 #7
sa*****@yahoo.co.in wrote:
....
And what is the reason that only copy constructor is invoked in this
case and why not the regular constructor?
Because it is defined that way in the standard. Passing by value by
definition requires the compiler to (appear to) create a temporary copy
of the object being passed. New copies of objects are created using the
copy constructor, almost by definition.
May 4 '07 #8

<sa*****@yahoo.co.inwrote in message
news:11**********************@c35g2000hsg.googlegr oups.com...
On May 4, 2:14 pm, Erik Wikström <eri...@student.chalmers.sewrote:
On 4 Maj, 11:03, sam_...@yahoo.co.in wrote:

It is created, but using the copy-constructor, which you have not
implemented so the compiler-generated one is used, and that one does
not print anything. Add

sample(const sample&) { std::cout << "copy\n"; }

to your class and see what happens.
And what is the reason that only copy constructor is invoked in this
case and why not the regular constructor?
Because you're creating a copy, obviously. That's what the copy constructor
is for. You're not creating a new object using no arguments. How else would
this work:
#include <iostream>

struct sample
{
int i;

sample() : i(0) { }
sample(int _i) : i(_i) { }
};

void foo(sample s)
{
std::cout << s.i << std::endl;
}

int main()
{
sample s(23);
foo(s);
}

If the temporary passed to foo() were to be default-constructed, you are
never able to pass the value 23 to foo. The copy-ctor is invoked to
construct a new sample that is a copy from the sample passed to foo(), so
you want the value 23 to be copied. This is the responsibility from the copy
constructor.

- Sylvester Hesp
May 4 '07 #9
On May 4, 2:59 pm, "Sylvester Hesp" <s.h...@oisyn.nlwrote:
<sam_...@yahoo.co.inwrote in message

news:11**********************@c35g2000hsg.googlegr oups.com...
On May 4, 2:14 pm, Erik Wikström <eri...@student.chalmers.sewrote:
On 4 Maj, 11:03, sam_...@yahoo.co.in wrote:
It is created, but using the copy-constructor, which you have not
implemented so the compiler-generated one is used, and that one does
not print anything. Add
sample(const sample&) { std::cout << "copy\n"; }
to your class and see what happens.
And what is the reason that only copy constructor is invoked in this
case and why not the regular constructor?

Because you're creating a copy, obviously. That's what the copy constructor
is for. You're not creating a new object using no arguments. How else would
this work:

#include <iostream>

struct sample
{
int i;

sample() : i(0) { }
sample(int _i) : i(_i) { }

};

void foo(sample s)
{
std::cout << s.i << std::endl;

}

int main()
{
sample s(23);
foo(s);

}

If the temporary passed to foo() were to be default-constructed, you are
never able to pass the value 23 to foo. The copy-ctor is invoked to
construct a new sample that is a copy from the sample passed to foo(), so
you want the value 23 to be copied. This is the responsibility from the copy
constructor.

- Sylvester Hesp
Thanks you very much. I understand the purpose of copy constructors
being used i would assume they are invoked for the following case too,

foo(s(23));

isn't it?

I also tried to define a constructor like

sample(sample obj) // i get an error saying first parameter
shouldn't be of type sample but the following works fine
sample(int i, sample obj)

why doesn't the first work? I pass an already existing object to the
constructor, a new temp object would be created with the help of copy
constructor and i'm using its value to create my object, what is wrong
in this scenario?

Thanks in advance!!!

May 4 '07 #10

<sa*****@yahoo.co.inwrote in message
news:11**********************@q75g2000hsh.googlegr oups.com...
>
Thanks you very much. I understand the purpose of copy constructors
being used i would assume they are invoked for the following case too,

foo(s(23));

isn't it?

I also tried to define a constructor like

sample(sample obj) // i get an error saying first parameter
shouldn't be of type sample but the following works fine
sample(int i, sample obj)

why doesn't the first work?
Because the standard says so:

12.8/3: A declaration of a constructor for a class X is ill-formed if its
first parameter is of type (optionally cv-qualified) X and either there are
no other parameters or else all other parameters have default arguments.

I don't know the exact reasons, but I can imagine some: first of all, it
can't be a copy ctor because the value would need to be copied itself,
resulting in an infinite recursion. If it isn't a copy ctor, that means
there exists a (auto-generated) copy ctor that is compatible with the same
parameter list, causing a call to either of the constructors to be
ambiguous, just as the following call is ambiguous:

void foo(int);
void foo(const int &);

int main()
{
foo(3); // error, call to foo() is ambiguous
}

Which effectively means that such an object can never be copy constructed.

- Sylvester Hesp
May 4 '07 #11
On May 4, 4:14 pm, "Sylvester Hesp" <s.h...@oisyn.nlwrote:
<sam_...@yahoo.co.inwrote in message

news:11**********************@q75g2000hsh.googlegr oups.com...
Thanks you very much. I understand the purpose of copy constructors
being used i would assume they are invoked for the following case too,
foo(s(23));
isn't it?
I also tried to define a constructor like
sample(sample obj) // i get an error saying first parameter
shouldn't be of type sample but the following works fine
sample(int i, sample obj)
why doesn't the first work?

Because the standard says so:

12.8/3: A declaration of a constructor for a class X is ill-formed if its
first parameter is of type (optionally cv-qualified) X and either there are
no other parameters or else all other parameters have default arguments.

I don't know the exact reasons, but I can imagine some: first of all, it
can't be a copy ctor because the value would need to be copied itself,
resulting in an infinite recursion. If it isn't a copy ctor, that means
there exists a (auto-generated) copy ctor that is compatible with the same
parameter list, causing a call to either of the constructors to be
ambiguous, just as the following call is ambiguous:

void foo(int);
void foo(const int &);

int main()
{
foo(3); // error, call to foo() is ambiguous

}

Which effectively means that such an object can never be copy constructed.

- Sylvester Hesp
Ok so you mean to say that the default copy constructor's prototype
would be

sample(sample&);

and my constructor's prototype would be

sample(sample)

and hence the compiler wouldn't know which call to resolve?
can you explain the recurssion part of it with an example?

Thanks in advance!!!

May 4 '07 #12
On 4 May, 12:31, sam_...@yahoo.co.in wrote:
On May 4, 4:14 pm, "Sylvester Hesp" <s.h...@oisyn.nlwrote:
<sam_...@yahoo.co.inwrote in message
sample(sample obj) // i get an error saying first parameter
shouldn't be of type sample but the following works fine
sample(int i, sample obj)
why doesn't the first work?
Because the standard says so:
12.8/3: A declaration of a constructor for a class X is ill-formed if its
first parameter is of type (optionally cv-qualified) X and either there are
no other parameters or else all other parameters have default arguments.
I don't know the exact reasons, but I can imagine some: first of all, it
can't be a copy ctor because the value would need to be copied itself,
resulting in an infinite recursion. If it isn't a copy ctor, that means
there exists a (auto-generated) copy ctor that is compatible with the same
parameter list, causing a call to either of the constructors to be
ambiguous, just as the following call is ambiguous:
void foo(int);
void foo(const int &);
int main()
{
foo(3); // error, call to foo() is ambiguous
}
Which effectively means that such an object can never be copy constructed.

Ok so you mean to say that the default copy constructor's prototype
would be
You might want to consider dropping the term "default copy
constructor" to avoid the risk of confusion with the "default
constructor". In the context of constructors, "default" has a
precisely defined meaning which is not applicable here. "implicitly-
declared copy constructor" might be better (that appears to be what
the language standard uses). "Compiler-generated copy constructor" is
another fairly popular and uncontroversial name for it. But "default
copy constructor" should probably be avoided.
sample(sample&);

and my constructor's prototype would be

sample(sample)

and hence the compiler wouldn't know which call to resolve?
Nearly. Generally, the implicitly-generated copy constructor has the
signature sample(const sample&). Only if a base class or member of
sample does *not* have the const in the signature of its own copy
constructor, will the signature of sample's copy constructor be
sample(sampl&) as you wrote.
can you explain the recurssion part of it with an example?
Think about it. Whenever an object is passed to a function by value,
the copy constructor is needed to initialise the function parameters.

void foo(T t1, T t2) {}

int main()
{
T a, b;
foo(a, b);
}

In the line foo(a, b) a and b (which are objects of type T) are passed
to function foo and used to initialise foo's parameters t1 and t2
respectively. t1 is a copy of a. t2 is a copy of b. Surprise, surprise
- to create t1 and t2 as copies of a and b, the copy constructor of
class T is used. That's how you make copies of objects.

Now what actually happens when the copy constructor of class T is
used? Imagine class T's copy constructor looks like this

T(const T& src);

and we are using that copy constructor to construct t1 from the source
object, a. t1 is the object under construction, and src is a reference
to the source object, a. That's important. src is not an object. It is
just a reference to a, an object that already exists. Whatever the
body of the copy constructor needs to do to initialise the internals
of the new object t1, it can do, because it can get at the internals
of the source object, a, through the reference, src.

Now, imagine we tried to use your signature for the copy constructor
here

T(T src);

This time src is an object, so in the process of calling this copy
constructor, the object src needs to be constructed. We are trying to
copy-construct t1 as a copy of a. But before we can start doing
whatever is in the body of the copy constructor, we need to construct
src, the parameter of the copy constructor. How do we construct src?
Well it needs to be a copy of a so I guess we need to use the copy
constructor.

That's the recursion. The very first thing that happens when we try
and use the copy constructor (to create t1 from a) is that we need to
use the copy constructor (to create the copy constructor's own
parameter src from a). But the very first thing that happens when we
try and use the copy constructor (this time to construct src from a)
is that we need to use the copy constructor .... and so, ad infinitum.
Put another way, the conversation goes like:

Me: "I need to know how to copy objects of type T because I have to
make t1 as a copy of a".
You: "OK. First of all, create yourself an object of type T called src
by copying a".
Me: "But I don't know how to copy objects of type T. That's what I'm
asking you".

Gavin Deane

May 4 '07 #13
On May 4, 1:31 pm, sam_...@yahoo.co.in wrote:
On May 4, 4:14 pm, "Sylvester Hesp" <s.h...@oisyn.nlwrote:
<sam_...@yahoo.co.inwrote in message
news:11**********************@q75g2000hsh.googlegr oups.com...
Thanks you very much. I understand the purpose of copy constructors
being used i would assume they are invoked for the following case too,
foo(s(23));
isn't it?
I also tried to define a constructor like
sample(sample obj) // i get an error saying first parameter
shouldn't be of type sample but the following works fine
sample(int i, sample obj)
why doesn't the first work?
Because the standard says so:
12.8/3: A declaration of a constructor for a class X is ill-formed if its
first parameter is of type (optionally cv-qualified) X and either thereare
no other parameters or else all other parameters have default arguments.
I don't know the exact reasons, but I can imagine some: first of all, it
can't be a copy ctor because the value would need to be copied itself,
resulting in an infinite recursion.
Which seems a rather obvious reason. If pass by value invokes
the copy constructor (which it does), then the copy constructor
itself obviously cannot take its parameter by value.
Ok so you mean to say that the default copy constructor's prototype
would be
sample(sample&);
The usual prototype is "sample( sample const& )". You do want
to be able to copy temporaries and const objects, don't you?
and my constructor's prototype would be
sample(sample)
and hence the compiler wouldn't know which call to resolve?
can you explain the recurssion part of it with an example?
Basically, if "sample( sample )" were a legal copy constructor,
to call it you'd first have to call it to pass the argument.

I'd strongly suggest you buy a copy of Scott Meyers' "Effective
C++", and study it. It covers all of these issues in a very
easy to understand way.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 4 '07 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Charles Jamieson | last post by:
I declare a class class myClass{ public: ~myClass();
7
by: Douglas Peterson | last post by:
Take a look at this code, it looks funny as its written to be as short as possible: -- code -- struct Base { ~Base() { *((char*)0) = 0; } }; struct Derived : public Base
8
by: ctick | last post by:
When defining a clas and no constructor and destructor provided, compiler generates both. What're the need for this since they do nothing as to constructing/destructing an obejct. What's...
23
by: Fabian Müller | last post by:
Hi all, my question is as follows: If have a class X and a class Y derived from X. Constructor of X is X(param1, param2) . Constructor of Y is Y(param1, ..., param4) .
5
by: manitu | last post by:
Hello all, I am writing a kind of encapsulation of SQL statements in C++ as a class. I am encountering problems that the destructor of my class never gets called. The class should be used as...
26
by: Prawit Chaivong | last post by:
Hi All, There is code here. ------------------------------------------------------------------ class Base{ public: Base(){} virtual ~Base(){} private: int a;
5
by: Frederick Gotham | last post by:
If we have a simple class such as follows: #include <string> struct MyStruct { std::string member; MyStruct(unsigned const i) {
12
by: Rahul | last post by:
Hi Everyone, I have the following code and i'm able to invoke the destructor explicitly but not the constructor. and i get a compile time error when i invoke the constructor, why is this so? ...
7
by: Rahul | last post by:
Hi Everyone, I was trying to implement a final class and i start having the destructor of the final class as private, class A { ~A() { printf("destructor invoked\n");
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.