Connecting Tech Pros Worldwide Forums | Help | Site Map

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

Michael
Guest
 
Posts: n/a
#1: Jan 5 '06
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







mlimber
Guest
 
Posts: n/a
#2: Jan 5 '06

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



Michael wrote:[color=blue]
> 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[/color]

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-lit....html#faq-10.6

Cheers! --M

Clark S. Cox III
Guest
 
Posts: n/a
#3: Jan 5 '06

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


On 2006-01-05 14:21:58 -0500, "Michael" <femi@hrz.tu-chemnitz.de> said:
[color=blue]
> 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[/color]

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).
[color=blue]
> }
>
> private:
> LowPassFilter LowCut;
>
> void doSomething();
> };[/color]

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();
};

[color=blue]
> 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.[/color]

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

--
Clark S. Cox, III
clarkcox3@gmail.com

Aleš Pergl
Guest
 
Posts: n/a
#4: Jan 5 '06

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


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

[color=blue]
> 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
>[/color]


Andre Kostur
Guest
 
Posts: n/a
#5: Jan 5 '06

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


"Michael" <femi@hrz.tu-chemnitz.de> wrote in
news:dpjrbc$mrb$1@anderson.hrz.tu-chemnitz.de:
[color=blue]
> 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.[/color]

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.
[color=blue]
> 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.[/color]

_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.
[color=blue]
> 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.[/color]

Sure, it would work. But as you point out, you'll have to manage the
lifetime of the pointer.
[color=blue]
> 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?[/color]

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...)
Closed Thread