Jump to content
Can't remember your login details? Read more... ×
Sign in to follow this  
NagChampa

Major flaw in VC++ 9 Express Edition

Recommended Posts

So, Microsoft really doesn't like to play ball when following things like standards do they?

 

In c++, there is an important difference between assignment and initialisation. Example:

 

int a = 1; //initialisation


int a;
a = 1; //assignment

There are two ways of writing an initialisation too:

 

int a = 1;


int a(1);

both of these should compile exactly the same way

 

This is especially important when it comes to class objects. For example, the following two lines of code should be equivalent (assuming a default constructor exists)

 

MyClass myClassObject = MyClass();

MyClass myClassObject();

However, in Microsoft Visual C++ Express Edition 9, they are not. I have a class for which I have declared a copy constructor, but haven't defined it yet. That is, there's no executable code yet. This shouldn't matter however because my test code doesn't have anything that should be calling the copy constructor. However, when I try to use the first form from the previous example in initialising my object, in VC++ i get a link error as it cannot find the copy constructor code. If I change it to the second form, it compiles correctly. It seems that Microsoft's compiler is trying to construct an unnamed variable then pass it to the copy constructor to construct my named variable with the first form.

 

Bad Microsoft.

Share this post


Link to post
Share on other sites

MyClass myClassObject = MyClass();

MyClass myClassObject();
Heh. Cool. I always thought you had to throw a new in there, and I just never knew about the second example (not a C++ programmer obviously :p)

Share this post


Link to post
Share on other sites

MyClass myClassObject = MyClass();

MyClass myClassObject();
Heh. Cool. I always thought you had to throw a new in there, and I just never knew about the second example (not a C++ programmer obviously :p)

 

Using new in c++ would give you a pointer to the object, it creates it on the heap instead of on the stack

 

In trying to come up with a basic example of the error, I discovered a mistake in my previous examples.

 

I thought the following should be equivalent:

 

MyClass foo;

MyClass foo();

However, the second one is ambiguous, and can be seen as a function prototype. While it's perfectly correct to initialise an object when the constructor takes arguments like this:

 

MyClass foo(14);

When you want to use the default constructor, you should leave off the parantheses completely.

 

Explained here: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.2

 

SO

 

I will fix my first post to show this.

 

I'll also post the example code when I'm finished it.

Share this post


Link to post
Share on other sites

Right. The thought of creating on object on the stack just seems weird to this C# programmer.

Share this post


Link to post
Share on other sites

MyClass myClassObject = MyClass();

MyClass myClassObject();

However, in Microsoft Visual C++ Express Edition 9, they are not. I have a class for which I have declared a copy constructor, but haven't defined it yet. That is, there's no executable code yet. This shouldn't matter however because my test code doesn't have anything that should be calling the copy constructor. However, when I try to use the first form from the previous example in initialising my object, in VC++ i get a link error as it cannot find the copy constructor code. If I change it to the second form, it compiles correctly. It seems that Microsoft's compiler is trying to construct an unnamed variable then pass it to the copy constructor to construct my named variable with the first form.

 

Bad Microsoft.

In VC++ the class operator= probably calls the non-existant copy constructor, whereas the second example simply allocates a 'MyClass'.

 

Just out of interest, I suspect if you had of 'new'ed it instead, it would work.

 

Don't quote me though, I'm still using Borland C++ 5.02!

Edited by Periander

Share this post


Link to post
Share on other sites

I could be wrong here, but isn't that C++ specification?

 

myClass object = myClass(args); //use standard constructor then use copy constructor e.g. myClass (const myClass &)

myClass object;

object = object; //use assignment (e.g. myClass & operator=(const MyClass&) )

myClass object(args); //implicit use of normal constructor

 

A call of say "MyClass myClassObject = MyClass();" will need a copy constructor (which is normally generated by the compiler for automatically if needed on build) and then a regular constructor

if you defined the copy constructor by say myClass(const myClass&); then the compiler will no longer generate the body of this constructor for you

 

maybe this will explain more: http://msdn.microsoft.com/en-us/library/c5at8eya.aspx

Edited by kickstep

Share this post


Link to post
Share on other sites

You may wonder why, but consider about dynamic memory allocation (heap).

MyClass object = MyClass(); may look the same as MyClass object();

but consider

MyClass a;

MyClass b = a; //not assignment, but initialization through copy constructor. MyClass() and a both have the same signature. Ambiguity.

and what if a contains a pointer to some data?

 

MyClass * a = new MyClass();

MyClass b = *a;

delete a; //Uhoh a's destructor is called, and that arbitary dynamic data no longer exists, and a default copy constructor wont consider that, and only do memberwise copy like a C style struct or other built in datatype

 

 

(also: MyClass b = a != MyClass b; b = a;)

Share this post


Link to post
Share on other sites

hrmm..

 

here's some code

 

class Foo {
 public:

  Foo() { cout << "I'm in yr ctor\n"; }

  Foo(const Foo& lolol) { cout << "I'm in yr copy ctor\n"; }
};

Foo f = Foo(); prints I'm in yr ctor indicating that Foo() rather than Foo(const Foo&) has been hit.

 

Foo g = f; prints I'm in yr copy ctor.

 

This is in g++ btw.

Edited by cobwebs in the sky

Share this post


Link to post
Share on other sites

I could be wrong here, but isn't that C++ specification?

 

myClass object = myClass(args); //use standard constructor then use copy constructor e.g. myClass (const myClass &)

myClass object;

object = object; //use assignment (e.g. myClass & operator=(const MyClass&) )

myClass object(args); //implicit use of normal constructor

 

A call of say "MyClass myClassObject = MyClass();" will need a copy constructor (which is normally generated by the compiler for automatically if needed on build) and then a regular constructor

if you defined the copy constructor by say myClass(const myClass&); then the compiler will no longer generate the body of this constructor for you

 

maybe this will explain more: http://msdn.microsoft.com/en-us/library/c5at8eya.aspx

The syntax

 

MyClass myClassObject = MyClass();

 

in C++ should be syntactic sugar for

 

MyClass myClassObject();

 

There's no assignment or copying going on. At least, that's how I learned it. I will try to find the full C++ spec and find out for sure. As far as I know, the following two lines are syntactically the same:

 

int i = 9;

int i(9);

 

That is, the int is initialised once to 9.

 

It would be excessive to call a constructor twice. You can't initialise the same memory location twice, so to call two constructors would also require twice the size of the object during the two initialisations. Seeing as the first format is common, they just treated it as the second.

Share this post


Link to post
Share on other sites

I could be wrong here, but isn't that C++ specification?

 

myClass object = myClass(args); //use standard constructor then use copy constructor e.g. myClass (const myClass &)

myClass object;

object = object; //use assignment (e.g. myClass & operator=(const MyClass&) )

myClass object(args); //implicit use of normal constructor

 

A call of say "MyClass myClassObject = MyClass();" will need a copy constructor (which is normally generated by the compiler for automatically if needed on build) and then a regular constructor

if you defined the copy constructor by say myClass(const myClass&); then the compiler will no longer generate the body of this constructor for you

 

maybe this will explain more: http://msdn.microsoft.com/en-us/library/c5at8eya.aspx

The syntax

 

MyClass myClassObject = MyClass();

 

in C++ should be syntactic sugar for

 

MyClass myClassObject();

 

There's no assignment or copying going on. At least, that's how I learned it. I will try to find the full C++ spec and find out for sure. As far as I know, the following two lines are syntactically the same:

 

int i = 9;

int i(9);

 

That is, the int is initialised once to 9.

 

It would be excessive to call a constructor twice. You can't initialise the same memory location twice, so to call two constructors would also require twice the size of the object during the two initialisations. Seeing as the first format is common, they just treated it as the second.

 

One problem with my argument here is the case of using the default constructor. The form:

 

MyClass myClassObject()

 

Becomes ambiguous apparently. The form:

 

MyClass myClassObject = MyClass();

 

still doesn't necessarily need a copy constructor. The spec does allow for it to though apparently.

 

Also, kickstep, no, didn't learn on C#.

Edited by NagChampa

Share this post


Link to post
Share on other sites

Actually, just reading this again. As you already pointed out, this:

 

Object obj();

Is a function forward declare. It's not a call to the default constructor, nor does it even remotely equate to:

 

Object obj = Object();

A default constructor call is just this:

 

Object obj;

However, confusingly if you wanted to call a constructor with a parameter, this is fine:

 

Object obj(1234);

I've tested your theory about default and copy constructors in VC++ 9 and BCC32 5.5 and BCC32 5.02, (the latter auto 'std::'s which is a pain), and they all produced the same result.

 

Here's a little demo:

 

#include <iostream>

class Object
{
	public:
		Object() { std::cout << "Object Default Constructor" << std::endl; };
		Object(const Object& rhs) { std::cout << "Object Copy Constructor" << std::endl; };
		~Object() { std::cout << "Object Destructor" << std::endl; };
};

void DoStuff()
{
	std::cout << "DoStuff Start" << std::endl;

	std::cout << "Object obj1();" << std::endl;
	Object obj1();

	std::cout << "Object obj2 = Object();" << std::endl;
	Object obj2 = Object();

	std::cout << "Object obj3 = obj2;" << std::endl;
	Object obj3 = obj2;

	std::cout << "Object obj4 = obj1();" << std::endl;
	Object obj4 = obj1();

	std::cout << "DoStuff Finish" << std::endl;

};

int main()
{
	DoStuff();

	std::cout << "Press ENTER...";
	std::cin.get();
	return 0;
};

Object obj1()
{
	Object ret;
	return ret;
}

Fool around with that commenting things out and you should get it.

Edited by Periander

Share this post


Link to post
Share on other sites

Yeah, like I said (did I?) I was probably wrong in my OP. And you are right, you can just use

 

MyClass myClassObject;

 

 

for the default copy constructor. Let's just say, I was getting myself more confused then I should have been :P

 

For he record, I think GCC doesn't use a copy constructor in the form

 

MyClass myClassObject = MyClass();

 

But I might check that.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×