473,395 Members | 1,856 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.

lifetime of static objects

Consider the following, incorrect, code:
#pragma hdrstop
#include <condefs.h>
#include <iostream>
#include <conio.h>

class bar
{
private:
operator = (const bar&);
bar(const bar&);
public:
bar(void)
{
cout << "bar: constructor " << std::endl;
}
~bar()
{
cout << "bar: destructor" << std::endl;
}
void Hello(int thing)
{
cout << "bar: say hello " << thing << std::endl;
}
void Goodbye(int thing)
{
cout << "bar: wave goodbye " << thing << std::endl;
}
};
class foo
{
private:
int thing_;
foo();
operator = (const foo&);
foo(const foo&);
static bar &instance()
{
static bar theInstance;
return theInstance;
}
public:
explicit foo(int thing):thing_(thing)
{
cout << "foo: constructor " << thing_ << std::endl;
bar& the_bar = instance();
the_bar.Hello(thing_);
}
~foo()
{
bar& the_bar = instance();
the_bar.Goodbye(thing_);
cout << "foo: destructor " << thing_ << std::endl;
}
};

static foo foo1(1);
static foo foo2(2);

int main(int argc, char **argv)
{
return 0;
}

The output from this is:

foo: constructor 1
bar: constructor
bar: say hello 1
foo: constructor 2
bar: say hello 2
bar: destructor
bar: wave goodbye 2
foo: destructor 2
bar: wave goodbye 1
foo: destructor 1

Which isn't what's required: methods in the static instance of bar are
being called after bar's destructor has been called.

How would I change the code to make sure that the static instance of
bar is destroyed last?

--
Simon Elliott http://www.ctsn.co.uk
Jul 22 '05 #1
7 1559
Simon Elliott wrote:
Consider the following, incorrect, code:
#pragma hdrstop
#include <condefs.h>
#include <iostream>
#include <conio.h>

class bar
{
private:
operator = (const bar&);
bar(const bar&);
public:
bar(void)
{
cout << "bar: constructor " << std::endl;
}
~bar()
{
cout << "bar: destructor" << std::endl;
}
void Hello(int thing)
{
cout << "bar: say hello " << thing << std::endl;
}
void Goodbye(int thing)
{
cout << "bar: wave goodbye " << thing << std::endl;
}
};
class foo
{
private:
int thing_;
foo();
operator = (const foo&);
foo(const foo&);
static bar &instance()
{
static bar theInstance;
return theInstance;
}
public:
explicit foo(int thing):thing_(thing)
{
cout << "foo: constructor " << thing_ << std::endl;
bar& the_bar = instance();
the_bar.Hello(thing_);
}
~foo()
{
bar& the_bar = instance();
the_bar.Goodbye(thing_);
cout << "foo: destructor " << thing_ << std::endl;
}
};

static foo foo1(1);
static foo foo2(2);

int main(int argc, char **argv)
{
return 0;
}

The output from this is:

foo: constructor 1
bar: constructor
bar: say hello 1
foo: constructor 2
bar: say hello 2
bar: destructor
bar: wave goodbye 2
foo: destructor 2
bar: wave goodbye 1
foo: destructor 1

Which isn't what's required: methods in the static instance of bar are
being called after bar's destructor has been called.

How would I change the code to make sure that the static instance of
bar is destroyed last?


You have to create it first. Pull the 'static bar theInstance' from
the function and place it in the file scope (without 'static') before
the other two objects. BTW, you didn't need "static" for them either,
unless you don't want them to be visible from other modules.

Victor
Jul 22 '05 #2
On 11/10/2004, Victor Bazarov wrote:
How would I change the code to make sure that the static instance of
bar is destroyed last?


You have to create it first. Pull the 'static bar theInstance' from
the function and place it in the file scope (without 'static') before
the other two objects.


That would make the objects harder to use. I want people to be able to
use a foo without thinking about a bar. (I'd like to be able to remove
all visibility of bar from my foo definition, but I suspect that's a
bridge too far.)
--
Simon Elliott http://www.ctsn.co.uk
Jul 22 '05 #3

How would I change the code to make sure that the static instance of
bar is destroyed last?


Destruction is always in reverse order of construction. So the only way to
ensure that bar is destroyed last is to construct it first.

john
Jul 22 '05 #4
* "Simon Elliott" <Simon at ctsn.co.uk>:
Consider the following, incorrect, code:
#pragma hdrstop
#include <condefs.h>
#include <iostream>
#include <conio.h>

class bar
{
private:
operator = (const bar&);
bar(const bar&);
public:
bar(void)
{
cout << "bar: constructor " << std::endl;
}
~bar()
{
cout << "bar: destructor" << std::endl;
}
void Hello(int thing)
{
cout << "bar: say hello " << thing << std::endl;
}
void Goodbye(int thing)
{
cout << "bar: wave goodbye " << thing << std::endl;
}
};
class foo
{
private:
int thing_;
foo();
operator = (const foo&);
foo(const foo&);
static bar &instance()
{
static bar theInstance;
return theInstance;
}
public:
explicit foo(int thing):thing_(thing)
{
cout << "foo: constructor " << thing_ << std::endl;
bar& the_bar = instance();
the_bar.Hello(thing_);
}
~foo()
{
bar& the_bar = instance();
the_bar.Goodbye(thing_);
cout << "foo: destructor " << thing_ << std::endl;
}
};

static foo foo1(1);
static foo foo2(2);

int main(int argc, char **argv)
{
return 0;
}

The output from this is:

foo: constructor 1
bar: constructor
bar: say hello 1
foo: constructor 2
bar: say hello 2
bar: destructor
bar: wave goodbye 2
foo: destructor 2
bar: wave goodbye 1
foo: destructor 1

Which isn't what's required: methods in the static instance of bar are
being called after bar's destructor has been called.

How would I change the code to make sure that the static instance of
bar is destroyed last?


The only sure way (i.e. without imposing "invisible" restrictions on usage)
would be to make bar instance reference counted. I think. You can find
an example of that idea in Andrei Alexandrescu's "Modern C++ Design".

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #5
>Destruction is always in reverse order of construction. So the only way to
ensure that bar is destroyed last is to construct it first.


Isn't that order based not on the order in which constructors were called but
the order in which constructors were completed?

In the OP's case the constructor for Foo is called first but the constructor
for Bar completes before the Foo constructor therefore the Bar destructor
should be called last because it was the first fully constructed object.

Not having the standard I can't provide support for this, but I did see it
discussed elsewhere on the net and the example code posted was virtually
identical to the OP's.


Jul 22 '05 #6

"DaKoadMunky" <da*********@aol.com> wrote in message
news:20***************************@mb-m02.aol.com...
Destruction is always in reverse order of construction. So the only way
to
ensure that bar is destroyed last is to construct it first.


Isn't that order based not on the order in which constructors were called
but
the order in which constructors were completed?

In the OP's case the constructor for Foo is called first but the
constructor
for Bar completes before the Foo constructor therefore the Bar destructor
should be called last because it was the first fully constructed object.

Not having the standard I can't provide support for this, but I did see it
discussed elsewhere on the net and the example code posted was virtually
identical to the OP's.


You are right, 3.6.3 para 1 says that destructors are called in reverse
order of the completion of their constructor calls.

Looks like the OP's compiler is not implementing this correctly.

john
Jul 22 '05 #7
On 12/10/2004, John Harrison wrote:
Isn't that order based not on the order in which constructors were
called but
the order in which constructors were completed?

In the OP's case the constructor for Foo is called first but the
constructor
for Bar completes before the Foo constructor therefore the Bar
destructor should be called last because it was the first fully
constructed object.

Not having the standard I can't provide support for this, but I did
see it discussed elsewhere on the net and the example code posted
was virtually identical to the OP's.


You are right, 3.6.3 para 1 says that destructors are called in
reverse order of the completion of their constructor calls.

Looks like the OP's compiler is not implementing this correctly.


That's entirely possible since it's BCB3 which is quite old.

But with BCB6 I get this:

foo: constructor 1
bar: constructor
bar: say hello 1
foo: constructor 2
bar: say hello 2
bar: destructor
bar: constructor
bar: wave goodbye 2
foo: destructor 2
bar: wave goodbye 1
foo: destructor 1

As you can see, bar is destroyed and then rebuilt. And then not
destroyed second time round. That doesn't seem right to me.

When I've got the chance I'll try this on gcc on my hosting provider's
unix box.

--
Simon Elliott http://www.ctsn.co.uk
Jul 22 '05 #8

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

Similar topics

5
by: Simon Elliott | last post by:
I have a C++ file which needs to work along these lines: class foo { private: int i1_; public: foo():i1_(12){} ~foo() {
5
by: Stuart MacMartin | last post by:
I have a problem with static lifetime (order of destruction of statics within different cpp files). I have a workaround that happens to work in my case. I'd like to know if this is luck or...
4
by: Terry | last post by:
There are a number of things about using unmanaged resources in Windows Forms programming that is unclear to me. In C++, if you loaded an icon resource using "ExtractIcon()", the resource was...
6
by: Richard Steele | last post by:
I have a static object that gets referenced at application startup. This object stores a dataset and various strings to be used whenever required. This object may be called at anytime to provide...
1
by: Eduardo Azevedo | last post by:
If I have a class with method Shared, when this objects are destroies what's happend with the objects Shared? How long is the lifetime of a function shared in the Class ? there are no...
16
by: anonymous.user0 | last post by:
The way I understand it, if I have an object Listener that has registered as a listener for some event Event that's produced by an object Emitter, as long as Emitter is still allocated Listener...
15
by: cedgington | last post by:
I wanted to take advantage of the large set of functionality offered by the framework, so for my latest project I'm using managed C++ with .NET v2. I'm using the gcnew operator in two different...
9
by: Chuck Cobb | last post by:
I am creating some static classes with static methods and static variables, but I have a question: What is the lifetime of static classes and static variables? Is there any risk that these...
9
by: David | last post by:
With a non-server app there is one instance of the program running and one user 'using' it at a time. With this scenario I'm pretty comfortable with variable scope and lifetime. With a server app...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
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...

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.