Answered Simple question on C++/CLI operators

  • Monday, July 31, 2006 12:59 PM
     
     

    What is the difference of these two?

    void Test1(RefClass^ s)

    and

    void Test2(RefClass^% s)

    I thought it is a way of distinguishing [in-out] parameters, but both of these functions can change the value of the handle passed to them. What is the other differences?

All Replies

  • Monday, July 31, 2006 10:14 PM
    Moderator
     
     Answered
    Try running this console code to see the difference:
    #include "stdafx.h"

    using namespace System;
    void test1(String^ s) {
      s = gcnew String("Hello world1");
    }
    void test2(String^% s) {
      s = gcnew String("Hello world2");
    }

    int main(array<System::String ^> ^args)
    {
      String^ s = gcnew String("Was it modified?");
      test1(s);
      Console::WriteLine("{0}", s);
      test2(s);
      Console::WriteLine("{0}", s);
      return 0;
    }

  • Tuesday, August 01, 2006 7:37 AM
     
     

    Sorry but my problem is about other ref types other than String^. I did the same thing with strings before posting my question and that was the cause of my surprise. I had seen that the ^% makes a [in-out] parameter with strings but it did not work on the RefClass I myself defined.

    This is what I'd done:

    using namespace System;

    public ref class RefClass

    {

    public:

    RefClass (int d)

    {

    m_nDims = d;

    }

    public:

    int m_nDims;

    };

    void TestR(RefClass^ s)

    {

    s->m_nDims = 10;

    }

    void TestHR(RefClass^% s)

    {

    s->m_nDims = 20;

    }

     

    int main(array<System::String ^> ^args)

    {

    RefClass^ refObject = gcnew RefClass(5);

    Console::WriteLine(refObject->m_nDims);

    TestR(refObject);

    Console::WriteLine(refObject->m_nDims);

    refObject->m_nDims = 0;

    TestHR(refObject);

    Console::WriteLine(refObject->m_nDims);

    return 0;

    }

    and the output is:

    5

    10

    20

     

  • Tuesday, August 01, 2006 11:50 AM
     
     

    What you did was not the same with what nobugz shown. Here it is:

     

    public ref class RefClass

    {

    public:

      RefClass (int d)

      {

        m_nDims = d;

      }

    public:

      int m_nDims;

    };

    void TestR(RefClass^ s)

    {

      s = gcnew RefClass(10);

    }

    void TestHR(RefClass^% s)

    {

      s = gcnew RefClass(20);

    }

    int main(array<System::String ^> ^args)

    {

      RefClass^ refObject = gcnew RefClass(5);

      Console::WriteLine(refObject->m_nDims);

      TestR(refObject);

      Console::WriteLine(refObject->m_nDims);

      TestHR(refObject);

      Console::WriteLine(refObject->m_nDims);

      return 0;

    }

  • Tuesday, August 01, 2006 11:57 AM
     
     Answered

    in this case

    void TestR(RefClass^ s)

    s is a handle, and it's passed by value. That means you can change the state of the object by accessing it through the handle, but if you change the handle itself, when the function returns, the change will be lost, because a copy of the handle was placed into the functions stack.

    void TestR(RefClass^ s) {

     s->m_nDims = 10; // this is ok, object's state is changed
    }

     

    void TestR(RefClass^ s) {

      s = gcnew RefClass(10); // this new handle will be lost when the function returns

    }

     

    On the other hand, on the second version,

    void TestHR(RefClass^% s)

    s is a tracking reference. Than means the handle is not passed by value (copy is made), but by reference. That means you can directly change the handle and the change will be known to the caller.

    void TestHR(RefClass^% s) {

     s->m_nDims = 10; // this is ok, object's state is changed
    }

    void TestHR(RefClass^% s) {

      s = gcnew RefClass(20); // this is also ok, because s is passed by reference and not by value

    }

    I hope these explanations make the things clear for you.

  • Wednesday, August 02, 2006 11:23 AM
     
     
    Thanks a lot, it helped me very much. Now I will look at the % operator as my familiar ref keyword in C#!!! I was trying to map it to & operator in C++ and I was lost!!!
  • Wednesday, August 02, 2006 12:23 PM
     
     
    Yeah, but it's the C++/CLI equivalent of the C++ reference operator for handles.
  • Wednesday, August 02, 2006 3:17 PM
     
     

    Definitely - for both value types and reference types.

    For example, the C# code:

    public void test(ref int valuetype, ref object reftype))
    {
    }

    converts to the following C++/CLI (obtained via our Instant C++ C# to C++/CLI converter):

    public:
    void test(int %valuetype, Object ^%reftype)
    {
    }

    David Anton
    www.tangiblesoftwaresolutions.com
    Instant C#: VB to C# converter
    Instant VB: C# to VB converter
    Instant C++: C# to C++ converter, VB to C++ converter
    Clear VB: Cleans up VB.NET code
    C# Code Metrics: Quick metrics for C#