0

I have a lot of C# Code that I have to write in C++. I don't have much experience in C++.

I am using Visual Studio 2012 to build. The project is an Static Library in C++ (not in C++/CLI).

I have a class with a static method with a static private member. When I debug I can see both the Constructor and the Copy Constructor being called. I don't understand why both get called, I thought only one would. Is there a way that I could make only one constructor get called?

This is my code

MyClass& MyClass::MyInstance()
{       
    static MyClass myLocalVariable = MyClass(/*parameters*/);
    return myLocalVariable ;
}

When the Method MyInstance gets called:

  1. First the Constructor of MyClass is called
  2. Then the CopyConstructor
  3. And then the "return myInstance" line.

Is it possible that the instance being held by myLocalVariable is only temporal and could get destroyed later on?

Update:

Since some people can not reproduce my problem, I am adding here more code. I have now 3 projects with the same behavior (one is a static library I am calling from my Unit Tests, and the other 2 are Win32 Console Applications)

C++ Main

int _tmain(int argc, _TCHAR* argv[])
{
    MyClass& instance = MyClass::MyInstance();

    return 0;
}

C++ MyClass.h

#pragma once
#include <string>

using namespace std;
class MyClass
{
private:
    string name;

public:
    MyClass(void);
    MyClass(string name);
    MyClass(const MyClass&);

    ~MyClass(void);

    static MyClass& MyInstance();   
};

C++ MyClass.cpp

#include "MyClass.h"
#include <iostream>
using std::cout;

MyClass::MyClass(void)
{
    cout << "Empty Cons\n";
}

MyClass::MyClass(string name)
{
    this->name = name;
    cout << "Parameters Cons\n";
}

MyClass::MyClass(const MyClass& myClass)
{
    name = myClass.name;
    cout << "Copy Cons\n";
}

MyClass::~MyClass(void)
{
    cout << "Destructor\n";
}

MyClass& MyClass::MyInstance()
{       
    cout << "MyInstance\n";
    static MyClass myInstance = MyClass("MyClassName");
    return myInstance;
}

My Output:

Myinstance

Parameters Cons

Copy Cons

Destructor

Dzyann
  • 5,062
  • 11
  • 63
  • 95
  • This isn't thread-safe in Visual Studio yet. So if you have more than one thread calling this, you've got a race. Also, directly translating C# designs to C++ designs will often get you into lots of trouble with memory management. – Sebastian Redl Nov 22 '13 at 12:29
  • 1
    Would be interesting to see what you got if you did `static MyClass myLocalVariable(/*parameters*/);`. This *should* be equivalent to what you have, at least for regular stack based variables. – TooTone Nov 22 '13 at 12:31
  • @SebastianRedl you are right about the memory problems! That is why I am trying to use objects like vector and string on C++ to minimize my problems. The original code is mostly for calculations. However I couldn't change the need for the Static Instances. My app is not multithreaded, but maybe Tests in Visual Studio are? – Dzyann Nov 22 '13 at 12:33
  • @TooTone I just tried what you said, and you only the first constructor gets called. Not the copy one. – Dzyann Nov 22 '13 at 12:40
  • @TooTone I debugged my code several times, and it always calls both constructors. What's more this is happening in 2 different programs. Because when I started to create problems I created a test project. Let me see if i can add more code so you can reproduce it. – Dzyann Nov 22 '13 at 13:46
  • Why do I get a downvote? Do I need to add more detail? – Dzyann Nov 22 '13 at 14:19
  • Please see this answer, http://stackoverflow.com/a/2462799/834521, re the different forms of creating objects, and the (subtle) differences between them. – TooTone Nov 22 '13 at 14:42

2 Answers2

3

Just write the variable as

static MyClass instance;

if there are no parameters, or

static MyClass instance(foo, bar);

if there are. Or since this is MSVC 2012, the uniform initialization syntax might be supported:

static MyClass instance{/*args here, could be empty*/};

This will initialize the variable in-place, instead of initializing a temporary and copying it to the target. (The compiler would be permitted to omit the copy, but apparently it doesn't in your case.)

Is it possible that the instance being held by myLocalVariable is only temporal

Note that first, the correct word is "temporary", and that second, myLocalVariable is the instance, it doesn't hold one. Unless you explicitly use pointers or references, C++ objects behave more like C# structs than classes, in that the variables don't hold references, they really are the objects.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • Thanks for pointing out the variable "is the instance", takes time to get used to the change from C# – Dzyann Nov 22 '13 at 12:43
1

Is it possible that the instance being held by myLocalVariable is only temporal and could get destroyed later on?

myLocalVariable is static hence will not be destroyed and would be available each time you make call to MyInstance

MyClass& MyClass::MyInstance()
{       
    static MyClass myLocalVariable = MyClass(/*parameters*/);
    return myLocalVariable ;
}

This would only invoke 1 constructor which is param constructor, as myLocalVariable is being returned by reference and not by value.

Nik
  • 1,294
  • 10
  • 16