After calling constructor, the destructor is called immediately - why?

M

mlimber

Michael said:
Hello,

I want to use an object (LowCut) within another object (SampleRateConverter)
like it is written as follows:

class SampleRateConverter
{
public:
SampleRateConverter( int iSourceSampleRate, int iTargetSampleRate )
{
LowCut = LowPassFilter(dCutoff, 512, BLACKMAN); // here
debugger calls first constructor and then destructor ~LowPassFilter
}

private:
LowPassFilter LowCut;

void doSomething();
};

I used the debugger and realized:
After calling the constructor for LowPassFilter within SampleRateConverter,
the destructor of LowPassFilter is called automatically.

That means, the Filter becomes destroyed immediately. So, I cannot use it in
the method doSomething. The Filter allocates a buffer in memory for storing
information.

But using LowPassFilter *LowCut; (pointer) (instead of the version written
above) and creating the Filter with new-operator (new LowPassFilter(..)) it
works?
Then I have to delete this Filter manually by calling delete LowCut.

But why I cannot use the first version? Why does the runtime environment
destroys the Filter object immediately after generating it?
Anything wrong due to OOP design issues?

Kind regards, Michael

Try using an initialization list instead:

class SampleRateConverter
{
public:
SampleRateConverter( int iSourceSampleRate, int iTargetSampleRate
)
: LowCut( LowPassFilter(dCutoff, 512, BLACKMAN) )
{}
// ...
};

See the FAQ:

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6

Cheers! --M
 
M

Michael

Hello,

I want to use an object (LowCut) within another object (SampleRateConverter)
like it is written as follows:

class SampleRateConverter
{
public:
SampleRateConverter( int iSourceSampleRate, int iTargetSampleRate )
{
LowCut = LowPassFilter(dCutoff, 512, BLACKMAN); // here
debugger calls first constructor and then destructor ~LowPassFilter
}

private:
LowPassFilter LowCut;

void doSomething();
};

I used the debugger and realized:
After calling the constructor for LowPassFilter within SampleRateConverter,
the destructor of LowPassFilter is called automatically.

That means, the Filter becomes destroyed immediately. So, I cannot use it in
the method doSomething. The Filter allocates a buffer in memory for storing
information.

But using LowPassFilter *LowCut; (pointer) (instead of the version written
above) and creating the Filter with new-operator (new LowPassFilter(..)) it
works?
Then I have to delete this Filter manually by calling delete LowCut.

But why I cannot use the first version? Why does the runtime environment
destroys the Filter object immediately after generating it?
Anything wrong due to OOP design issues?

Kind regards, Michael
 
?

=?iso-8859-2?Q?Ale=b9=20Pergl?=

You are creating a temporary LowPassFilter object who's scope is only the
assignment operation. If LowPassFilter has a proper copy constructor than
your code should work but isn't optimal because you are creating two LowPassFilters
instead of one. In fact, you are creating three because one more is created
upon initialization of the object (by LowPassFilter's default constructor).
mlimber's advice to use the initialization list saves you the default instance
but still creates a temporary and copies it to your member variable. The
correct way to do this is like so:

class SampleRateConverter
{
private:
LowPassFilter LowCut;

public:
SampleRateConverter( int iSourceSampleRate, int iTargetSampleRate ) :
LowCut(dCutoff, 512, BLACKMAN)
{
// ...
}

void doSomething() { /* work with LowCut */ }
};

Ales
 
A

Andre Kostur

Hello,

I want to use an object (LowCut) within another object
(SampleRateConverter) like it is written as follows:

class SampleRateConverter
{
public:
SampleRateConverter( int iSourceSampleRate, int
iTargetSampleRate ) {
LowCut = LowPassFilter(dCutoff, 512, BLACKMAN); // here
debugger calls first constructor and then destructor ~LowPassFilter
}

private:
LowPassFilter LowCut;

void doSomething();
};

I used the debugger and realized:
After calling the constructor for LowPassFilter within
SampleRateConverter, the destructor of LowPassFilter is called
automatically.

From a pessimistic compiler, you may have 2 constructors, an assignment,
and a destructor called:

- LowCut is default constructed (at the time that SampleRateConverter
is...)
- A temporary LowPassFilter is constructed for the purposes of the
assignment
- As assignment between the temporary and LowCut is performed
- The temporary LowPassFilter is destroyed.
That means, the Filter becomes destroyed immediately. So, I cannot use
it in the method doSomething. The Filter allocates a buffer in memory
for storing information.

_A_ Filter (I presume you really mean LowPassFilter) is destroyed.
There's two of them in there.... since Filter is allocating a buffer, you
may not have correctly implemented your assignment operator.
But using LowPassFilter *LowCut; (pointer) (instead of the version
written above) and creating the Filter with new-operator (new
LowPassFilter(..)) it works?
Then I have to delete this Filter manually by calling delete LowCut.

Sure, it would work. But as you point out, you'll have to manage the
lifetime of the pointer.
But why I cannot use the first version? Why does the runtime
environment destroys the Filter object immediately after generating
it? Anything wrong due to OOP design issues?

Likely because you've violated the "Rule of three": "If a class needs a
destructor, or a copy constructor, or an assignment operator, it needs
them all." What's probably happening is that during the assignment, it's
only copying the pointer that you allocated to in the LowPassFilter.
When the temporary goes out of scope, it probably deletes the memory that
it holds. As a result, you still have a dangling pointer stored inside
of LowCut. When you try to do something with it later on, you get
Undefined Behaviour (it may crash, it may not... luck of the draw...)
 
C

Clark S. Cox III

Hello,

I want to use an object (LowCut) within another object
(SampleRateConverter) like it is written as follows:

class SampleRateConverter
{
public:
SampleRateConverter( int iSourceSampleRate, int iTargetSampleRate )
{
LowCut = LowPassFilter(dCutoff, 512, BLACKMAN); // here
debugger calls first constructor and then destructor

That is because you are creating a temporary object with the
expression (LowPassFilter(dCutoff, 512, BLACKMAN)). This temporary is
then copied via assignment to the instance variable LowCut, and is then
destroyed (hence the call to the destructor).
}

private:
LowPassFilter LowCut;

void doSomething();
};

Try this (this avoids the creation of a temporary object, and
initializes the member variable directly):

class SampleRateConverter
{
public:
SampleRateConverter( int iSourceSampleRate, int iTargetSampleRate )
: LowCut(dCutoff, 512, BLACKMAN)
{}

private:
LowPassFilter LowCut;

void doSomething();
};

I used the debugger and realized:
After calling the constructor for LowPassFilter within
SampleRateConverter, the destructor of LowPassFilter is called
automatically.

That means, the Filter becomes destroyed immediately. So, I cannot use
it in the method doSomething. The Filter allocates a buffer in memory
for storing information.

this suggests to me that you haven't properly implemented an assignment
operator (or, odds are, copy constructor) for the class LowPassFilter.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top