views:

466

answers:

2

Cheers,

I ran into this chunk of code in "Programming Game AI by Example":

/* ------------------ MyClass.h -------------------- */
#ifndef MY_SINGLETON
#define MY_SINGLETON

class MyClass
{
private:

  // member data
  int m_iNum;

  //constructor is private
  MyClass(){}

  //copy ctor and assignment should be private
  MyClass(const MyClass &);
  MyClass& operator=(const MyClass &);

public:

  //strictly speaking, the destructor of a singleton should be private but some
  //compilers have problems with this so I've left them as public in all the
  //examples in this book
  ~MyClass();

  //methods
  int GetVal()const{return m_iNum;}
  static MyClass* Instance();
};

#endif

/* -------------------- MyClass.cpp ------------------- */

//this must reside in the cpp file; otherwise, an instance will be created
//for every file in which the header is included
MyClass* MyClass::Instance()
{
  static MyClass instance;

  return &instance;
}

I am confused by the matter-of-fact statement by the author that the statically declared variable inside a function in header would result in declaring multiple, separate static variables instance. I don't think I've seen this behavior in my usual implementations of getInstance() function which I regularly put into headers (except that I like playing with pointers and initializing the singleton upon first use). I'm using GCC for my work.

So what does the standard say? What do non-compliant compilers say? Is the author's statement correct, and if so, can you name some compilers which would create multiple instances if getInstance() were declared in headers?

+5  A: 

In C++ nothing prevent an inline function to have a static variable and the compiler has to arrange to make that variable common between all translation units (like it has to do it for template instantiation static class members and static function variables). 7.1.2/4

A static variable in an extern inline function always refer to the same object.

Note that in C, inline functions can't have static variables (nor reference to object with internal linkage).

AProgrammer
In other words, a 'static variable' defined in a 'static inline function' in myclass.h will appear only once in resulting linked code, and will be shared between source files (such as main.cpp, myclass.cpp and joetheplumber.cpp)? Moving ::Instance() from above code into header will still guarantee having same instance being returned to different .cpp files?
Ivan Vučica
As long as the compiler is conforming. As I don't remember any problem and the hability is needed for template, I've no fear on that point.
AProgrammer
Haven't heard about recent problems with this, nor in VC6 or GCC 2.95.
MSalters
Someone mentioned shared objects/DLL, I just checked Linux and Solaris and they have no problem with them.
AProgrammer
+1  A: 

I've tried the code that the OP posted with VS2008 in four ways and there doesn't seem to be a problem with the static instance of MyClass inside MyClass::Instance().

  1. Instance() is defined in MyClass.cpp: This is the normal way everything is fine.
  2. Instance() is defined only inside the class declaration. This is the alternative and everything is fine.
  3. Instance() is defined inline outside the class, but in the header and everything is fine.
  4. as 3. but without the inline and the linker says there are mutiple definitions of Instance()

I think that the book author is concerned with 4. above and knows that the static instance of MyClass will be taken care of in a program that compiles and links.

quamrana
I'd mark you as accepted, but I already did that with AProgrammer and I'd feel really bad about switching the tick. So here's just an upvote for a very clear reasoning.
Ivan Vučica