More Meyers Singleton woes with VC++

Started by
13 comments, last by level10boy 21 years, 8 months ago
While we're on the subject, would using a static class member variable be O.K. as opposed to a static variable inside a member function?


      // cA.hclass A{public:   ~A(void)   {      if(mInstance)         delete mInstance;   }public:   inline static A &Instance(void)   {      if(!mInstance)         mInstance = new A;      return *mInstance;   }private:   A(void);   static A* mInstance;};// cA.cppA::A() {}A* A::mInstance = 0;      


This thread just royally confused me I could just move the Instance code outside the class declaration to avoid inlining it (and removing the 'inline' keyword, duh), but I need to know if this is fine!

[edited by - Zipster on July 29, 2002 6:23:39 PM]
Advertisement
Zipster, that is fine. Only one instance of the static
class member variable is ever instantiated in whichever CPP
file you define it. A static class member variable is
like extern , but you stuff it under the class
rather than leaving it in the global namespace.

Let me say it again. inline function(s) with
static variable(s) is a BAD idea. Some compilers
(e.g. VC++ 6) just can''t deal with it and result in multiple
copies of the static variable(s) being instantiated. The
only way to be sure is to NEVER inline functions with
static variables.

P.S. This is taken from, appropriately enough, Scott Meyers
pair of books -- Effective C++ and More Effective C++.


Kami no Itte ga ore ni zettai naru!
神はサイコロを振らない!
quote:Original post by tangentz
Not if the compiler is "faulty". Shared() is copied as
many times as it is inlined, causing multiple instances
of the static variables to be present. See MEC++. The only
way to be sure is to make Shared() non-inline.


I agree. The 1996 C++ standard corrects this behaviour. If it was a pre 1996 compiler, I would expect it to have this problem. But VC++6 ? (Well, I''m won''t too surprised if it has that bug)

quote:
Sorry, but this is wrong. A static function exists ONLY
in the translation unit (CPP) where it is compiled in. You
can''t even extern and use it, because it has internal linkage.
Only ONE instance of this is present.


I am assuming you put it in a header file like the inlined version.

Take a look at this code( VC++ 6sp5 - full optimizations, inlined whereever suitable)


  // %%%%%% C.h %%%%%#include <iostream>class	C{public:	static	void	Method();};inline	void	C::Method(){	static	int	count;	std::cout << ++count << "\n";}//%%%%% another.cpp %%%%%#include "C.h"void	F(){	C::Method();   // breakpoint}//%%%%% main.cpp %%%%%%#include "C.h"extern	void	F();int	main(){	C::Method();	F();     // breakpoint	return	0;}  


The output printed is 1,2. As expected.

Looking at the disassembly



//%%%%% main.cpp %%%%%

5: int main()
6: {
00401000 mov eax,[count (0041ef84)]
00401005 push offset string "\n" (0041b070)
0040100A inc eax
0040100B mov ecx,offset std::cout (0041eb38)
00401010 push eax
00401011 mov [count (0041ef84)],eax
00401016 call std::basic_ostream >::operator<< (00401030)
0040101B push eax
0040101C call std::operator<< (00401490)
00401021 add esp,8
7: C::Method();
8:
9: F();
00401024 call F (00403970)
10:
11: return 0;
00401029 xor eax,eax
12: }
0040102B ret


// %%%%% another.cpp %%%%%
3: void F()
4: {
00403970 mov eax,[count (0041ef84)]
00403975 push offset string "\n" (0041b070)
0040397A inc eax
0040397B mov ecx,offset std::cout (0041eb38)
00403980 push eax
00403981 mov [count (0041ef84)],eax
00403986 call std::basic_ostream >::operator<< (00401030)
0040398B push eax
0040398C call std::operator<< (00401490)
00403991 add esp,8
5: C::Method();
6: }
00403994 ret


C::Method() looks inlined to me and it produces the correct results.

You can try it with a inlined non member function and it still shows the correct results.


  //%%%% C.h %%%#include <iostream>// if this is static, then it is a totally different storyinline	void	C(){	static	int	count;	std::cout << ++count << "\n";}//%%%% another.cpp %%%%#include "C.h"void	F(){	C();}//%%%%% main.cpp %%%%#include "C.h"extern	void	F();int	main(){	C();	F();	return	0;}  

[/source]
Try a third variation: Put the function calling the inline
method in question in a separate static library and link the
main EXE with the .lib and see what happens. Actually,
why don''t we make 3 or more of "F()" and have some fun?


Kami no Itte ga ore ni zettai naru!
神はサイコロを振らない!
quote:Original post by tangentz
Try a third variation: Put the function calling the inline
method in question in a separate static library and link the
main EXE with the .lib and see what happens. Actually,
why don''t we make 3 or more of "F()" and have some fun?


Something must be wrong with my VC++ 6 . It produces the correct results everytime. Perhaps you like to send me your test case.

This topic is closed to new replies.

Advertisement