Cluebat-man to the rescue

A weblog dedicated to Visual C++, interoperability and other stuff.

Differences between C# and C++/CLI, part 1

Learning C# if you already know C++ is relatively easy. The syntax is similar, and the semantics are definitely a lot easier to understand.

Since C# looks like C++, most of the concepts are easy to learn, but here and there are a few details that might cause problems later on.

On of these things is the difference between the meaning of classes and structures in C# and C++.

C++

With C++, a distinction needs to be made between native C++ and C++/CLI

Native C++

Classes and structures are virtually identical in native C++. Instances can be located on the stack or on the heap. It all depends on how they are instantiated.

The only difference between the two is that in a class, the default access of a class member is private, while the default access of a structure member is public.

That’s all there is to it.

C++/CLI

With the rise of C++/CLI, the compiler needs to know

a)      whether a type is managed or unmanaged, and

b)      whether the type (if managed) is a reference or value type.

To solve this, the new keywords ‘ref’ and ‘value’ are used. The term ‘ref type’ indicated a reference type. The type is managed, and is located on the managed heap. The term ‘value type’ indicates a managed value type. It is also managed, but located on the stack

Type can be either a class or a structure. As a result, it is possible for classes to be value types, and structures to be reference types in C++.

Semantics

In C++, the way in which you instantiate – and not the declaration – of a type determines whether it lives on the heap or on the stack.

2 important consequences of type location in C++ are that stack based instances are fixed in memory during their lifetime, and that stack based instances are guaranteed to be cleaned up when the go out of scope.

In reality, the C++ compiler is cheating you. It does some things behind your back to fool you into thinking that things live on the stack, while in reality they live on the managed heap.

  • Native types are either allocated on the stack or the native heap, based on whether you use stack semantics or operator new.
  • Value types can be created on the stack, on the native heap and on the managed heap, based on whether you instantiate them using stack semantics, operator new, or operator gcnew. But still, what you see is what you get.
  • Reference types are always created on the managed heap. Even if you use stack semantics for instantiating a reference type, the compiler still allocates the object on the managed heap. The compiler then takes care to insure that the object behavior (like deterministic cleanup etc…) mimics what you would expect of a stack based object.

If you are programming C++ in a mixed mode environment (both native and managed code in the same module) it is important to be aware of these possibilities and their impact.

C#

C# has a type system that is a lot easier to grasp.

Classes are reference types. They are always created on the managed heap.

Structures are value types. They are always created on the stack. C# -like C++/CLI- also supports the concept of boxing, where a copy of the value type is saved on the managed heap.

Conclusion

C# and C++/CLI share some type traits. The cases that are identical in C++/CLI and C# are in the following table:

 

C#

C++/CLI

Value type

struct

value class

Reference type

class

ref struct

 

All other types in C++ and C++/CLI do not have a 100% equivalent in C#.

When building class libraries for use in other .NET enabled languages, you have to watch out for incompatibilities that can be caused by using C++/CLI specific types.
Posted: Aug 31 2006, 03:56 PM by vanDooren | with 2 comment(s)
Filed under: , ,

Comments

ytosa said:

What is the corresponding C# "out" for C++/CLI?

C# you can have foo (out int [] a)  or foo (ref int [] a)

I know how to do the second one in C++/CLI like

foo( array<int>^% a)

Can you tell the first one in C++/CLI?

# November 10, 2007 11:07 PM

vanDooren said:

Hi sorry for the late repIy. It was a busy couple of weeks.

I have not really looked into this, but C++ does not know the notion of output only.

It is either by reference or by value.

DCOM has the notion of input / output or both, but that is a marshaling issue. Marshaling only takes place for the IO direction that was specified in the IDL declaration.

# November 26, 2007 3:09 PM