Click here to Skip to main content
15,885,216 members
Articles / Programming Languages / C++/CLI
Article

Using value types in managed C++

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
15 Oct 2001CPOL3 min read 72.4K   725   19  
A quick introduction to using .NET value types in managed C++

Introduction

Managed reference types in .NET are objects that contains methods and properties and which live their lives on the .NET managed heap. There are situations, however, where you do not want the overhead associated with creating and destroying objects on the heap. When dealing with simple data structures such as an integer or an (x,y) coordinate it is far more convenient - and efficient - to allocate these values directly on the stack and work with them using the standard value type semantics. No one wants to have to write
int* n = new int();

when declaring an integer (or array of 10,000 integers!). Instead, primitive types such as numeric types, boolean, char and date, structures and enumerations are all declared as value types, meaning they are allocated on the stack and declared and accessed as you would a structure or stack-based variable in standard C++.

Declaring and Creating Value Types

To declare a value type in managed C++ you use the new __value keyword. For instance, if we wished to create a data type to represent complex numbers we could declare the following:

__value struct Complex
{
    double real;
    double imaginary;
};

Value types are created on the stack and are accessed directly. Value types are declared

Complex z;

and their members accessed using the . syntax

z.real = 1.0;
z.imaginary = -3.1415;

Once the memory containing a value type is freed, the value type instance is destroyed. Hence, references to value types are not allowed. If it were allowed it would be possible to have a reference point to an invalid memory location. A value type will always point to a variable of that type, and cannot be null. Assigning a value type to another variable results in a copy of the value being made.

Because value types are managed types, they are initialised to 0 when they are created. Value types can contain reference types, though these reference types will be created on the managed heap and the reference to them stored on the stack.

Value types implicitly inherit from System.ValueType, and their use is encouraged for types that act like primitive data types, types that are small, types that do not inherit from, or are inherited by, other data types, and types that are not frequently passes as parameters (this would cause a lot of memory allocation and copying). Value types can inherit from managed interfaces, and can override virtual methods defined therein.

One important point with all value types is that they do can contain methods and fields, and you can override virtual methods from base interfaces. For instance, we may wish to override the ToString method for our complex type so that we can present it in a formatted manner

__value struct Complex
{
    double real;
    double imaginary;

    virtual String *ToString()
    {
        return String::Format("{0} + {1}i", real.ToString("N2"), imaginary.ToString("N2"));
    }
};

Boxing and Unboxing

Boxing is a feature that allows a value type to be passed around as a reference type. For instance, one of the the standard Format method overrides of the .NET String class takes a format string and an object.

public: static String* Format(String*, Object*);

The format string specifies the format, and the object is accessed within that format string using the {0} syntax. An int is not derived from Object and hence cannot normally be passed to this function. However, by boxing an integer value we are creating an object that will contain the value of the integer and can be used as an object. The syntax is

object obj = __box(5);

This creates a managed reference on the managed heap containing the value '5'. This object can now be used wherever an Object* object is required.

We can also declare boxed value types like

__box Complex* pZ = __box(z);

This gives us an object we can use in whatever way we deem fit, but in doing so we retain the ability to access the underlying type's data fields

pZ->real = 4;

Once we are done using the value in its boxed form we can unbox the value using the C++ dynamic_cast operator

Complex w = * dynamic_cast<Complex*>(pZ);

History

26 Apr 2001 - added sample app

16 Oct 2001 - updated source for VS.NET beta 2

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder CodeProject
Canada Canada
Chris Maunder is the co-founder of CodeProject and ContentLab.com, and has been a prominent figure in the software development community for nearly 30 years. Hailing from Australia, Chris has a background in Mathematics, Astrophysics, Environmental Engineering and Defence Research. His programming endeavours span everything from FORTRAN on Super Computers, C++/MFC on Windows, through to to high-load .NET web applications and Python AI applications on everything from macOS to a Raspberry Pi. Chris is a full-stack developer who is as comfortable with SQL as he is with CSS.

In the late 1990s, he and his business partner David Cunningham recognized the need for a platform that would facilitate knowledge-sharing among developers, leading to the establishment of CodeProject.com in 1999. Chris's expertise in programming and his passion for fostering a collaborative environment have played a pivotal role in the success of CodeProject.com. Over the years, the website has grown into a vibrant community where programmers worldwide can connect, exchange ideas, and find solutions to coding challenges. Chris is a prolific contributor to the developer community through his articles and tutorials, and his latest passion project, CodeProject.AI.

In addition to his work with CodeProject.com, Chris co-founded ContentLab and DeveloperMedia, two projects focussed on helping companies make their Software Projects a success. Chris's roles included Product Development, Content Creation, Client Satisfaction and Systems Automation.

Comments and Discussions

 
-- There are no messages in this forum --