How to pass by reference in C++ .net?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • BahatiSiD
    New Member
    • Oct 2008
    • 9

    How to pass by reference in C++ .net?

    Code:
    int y;
    void square(int x, int& result)
        {
         result = x*x;
         }
    ...
    square(3,y);
    this code compiles and works in DevCpp (native C++), but not in VS2008 .net C++

    it says: error C2664: cannot convert parameter 2 from 'int' to 'int &' (on the line where i call the function)


    can someone please tell me what can be done?
  • looker
    New Member
    • Dec 2007
    • 18

    #2
    Try this :

    1. int y;
    2. void square(int x, int *result)
    3. {
    4. *result = x*x;
    5. }
    6. ...
    7. square(3, &y);

    Comment

    • BahatiSiD
      New Member
      • Oct 2008
      • 9

      #3
      it now says: error C2664: cannot convert parameter 2 from 'cli::interior_ ptr<Type>' to 'int *' on the same line.

      the more i think about it the original code should not work at all? the function body says: the address of y = x*x
      not: the value on the addres of y = x*x as it should?

      please correct me if i'm wrong, as i am a noob. :)

      your code makes much more sence!

      and guess what, it does work! thank you very much!
      it just needed a minor adjusment, based on the error output.

      Code:
      int y; 
      square(int x, interior_ptr<int> result)
           {
           *result = x*x;
           }
      ...
      square(3,&y);
      i used this for reference: http://msdn.microsoft.com/en-us/libr...xx(VS.80).aspx

      of course i like the original code much better because it seems simpler. does anyone know why it compiles in DevCpp native c++, and not in C++/CLR? or has an idea how to simplify the solution that does work?

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        This code:
        Code:
        int y; 
        void square(int x, int& result) 
            { 
             result = x*x; 
             } 
        int main()
        {
        	square(3,y); 
        }
        compiles and links on my Visual Studio.NET 2008.

        There's something you're not telling us.

        Comment

        • BahatiSiD
          New Member
          • Oct 2008
          • 9

          #5
          These are the steps I’ve taken to try this out, and indeed I take whenever I’m making an application.

          In visual studio 2008 I click on file>new>projec t, select visual c++ in project types and windows forms application in templates.

          In an 'empty' project I get a 'Form.h'. The last lines in that file are:
          Code:
          #pragma endregion
          };
          }
          I write my code between lines 1 and 2.

          This is how it looks:
          Code:
          #pragma endregion
          	int var1;
          	int var2;
          	
          	//SHOULD WORK
          	/*
          	public: void square(int x, int& result) {
          				result = x*x;
          			}
          	*/
          	
          	//DOES WORK
          	public: void square(int x, interior_ptr<int> result) {
          				*result = x*x;
          			}
          
          	//SHOULD WORK
          	/*
          	public: void swap (int& x, int& y) {
          				int temp = x;
          				x = y;
          				y = temp;
          			}
          	*/
          
          	//DOES WORK
          	public: void swap (interior_ptr<int> x, interior_ptr<int> y) {
          				int temp = *x;
          				*x = *y;
          				*y = temp;
          			}
          	
          	private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
          				 var1 = 5;
          				 var2 = 9;
          			 }
          
          	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
          				 textBox1->AppendText("BEFORE SWAP - Var1: " + var1.ToString() + " Var2: " + var2.ToString() + "\r\n");
          				 //swap(var1,var2);
          				 swap(&var1,&var2);
          				 textBox1->AppendText("AFTER SWAP - Var1: " + var1.ToString() + " Var2: " + var2.ToString() + "\r\n");
          			 }
          
          	private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
          				 textBox1->AppendText("BEFORE SQUARE (var2 = var1^2) - Var1: " + var1.ToString() + " Var2: " + var2.ToString() + "\r\n");
          				 //square(var1,var2);
          				 square(var1,&var2);
          				 textBox1->AppendText("AFTER SQUARE (var2 = var1^2) - Var1: " + var1.ToString() + " Var2: " + var2.ToString() + "\r\n");
          			 }
          };
          }
          I’ve added two buttons for calling the pass by reference functions to best simulate practical use and a textbox (multiline, with vertical scrollbar) to act as a console. The last three functions are event handlers. The first one is called on load to init the variables. The other two handle the button clicks.

          Can you please elaborate on the steps you've taken? How do you start a new project and where do you write your code?

          It’s the only thing I can think of that could make a difference. It’s quite possible I’m doing something horribly wrong...

          Comment

          • vinayvaka
            New Member
            • Nov 2007
            • 13

            #6
            It should work.
            call by referece means you have to take like that only
            void mul(int a, int& sum)
            {
            sum=a*a;
            }

            void main()
            {
            int a=10;
            int sum;
            mul(a,sum);
            printf("%d",sum );
            }

            in this case i will print 100 thats sure.. i wont give any error try this agian and let me know if not............ ...

            Comment

            • l034n
              New Member
              • Oct 2008
              • 15

              #7
              Ok, i see some things have been confused here and it has to do with the way the variables are declared... The example of vinayvaka will work as will many of the above examples (even though they didn't work for BahatiSiD). So, why?
              Or... although the example of vinayvaka works as it is, if BahatiSiD tries it with his variables, it won't, i guarantee you that.
              Well, BahatiSiD have declared his variables on the heap, hence they're not local variables allocated on the stack. You may ask what does it have to do with all this, but remember that this is MC++ and not ANSI C++. So, you can't pass the variables that are on the heap the same way as the local variables. The problem is that in a managed environment, the address of a variable allocated on the heap might change (and will change during the lifetime of a program numerous times, hence it is not safe to use it that way).
              I could write this function:

              Code:
              void Swap(int& x, int& y)
              	{
              		int temp = x;
              		x = y;
              		y = temp;
              	}
              and using textBoxes as in BahatiSiD's example call it this way:

              Code:
              int num1 = 15;
              int num2 = 30;
              
              textBox->AppendText("--------------------" + Environment::NewLine);
              textBox->AppendText("BEFORE x = " + num1.ToString() + ", y = " + num2.ToString() + Environment::NewLine);
              Swap(num1, num2);
              textBox->AppendText("AFTER  x = " + num1.ToString() + ", y = " + num2.ToString() + Environment::NewLine);
              and it will work like a charm. But, if i call it this way:

              Code:
              textBox->AppendText("--------------------" + Environment::NewLine);
              textBox->AppendText("BEFORE x = " + var1.ToString() + ", y = " + var2.ToString() + Environment::NewLine);
              Swap(var1, var2);
              textBox->AppendText("AFTER  x = " + var1.ToString() + ", y = " + var2.ToString() + Environment::NewLine);
              I'll get an error:
              error C2664: 'TestProject::F orm1::Swap' : cannot convert parameter 1 from 'int' to 'int &'

              Note that i just used BahatiSiD's variables as he has declared them. I am making this example so that BahatiSiD can try it out in his sample project.
              So, what the heck...
              We're telling the compiler that Swap() takes 2 int&, and it's fine, but why in the first example the compiler passed our variables by-reference, and the second time it did not?
              As i previously said, you cannot use ordinary native C++ pointers with the garbage-collected heap because if the location of the data pointed to changes, the pointer will no longer be valid.
              So, what we need now is a way to access the object on the heap that enables the address to be updated when the gc will reallocate the data item on the heap. We have 2 ways at our disposal:
              1. Tracking handle (or simply, handle), which is analogous to a pointer in native C++
              2. Tracking reference (equivalent to a reference in native C++)

              So... they act pretty much as their counterparts in native c++ (as much as the programmer might be concerned, although he should understand the fundamental differences, because they really are different), but don't forget the keyword TRACKING. They track the address of the object on the heap, so you always have a valid pointer/address.
              That's why the examples with interior_ptr<in t> worked, because interior_ptr<Ty pe> is managed by the CLR and the address is accordingly updated whenever the GC collects.
              So, in order to make it work, you may use interior_ptr<in t>, or if you want to use the forementioned Swap() function (or any other function of that type) and make it work, you may "cheat" a little bit this way:

              Code:
              int num1 = var1;
              int num2 = var2;
              
              textBox->AppendText("--------------------" + Environment::NewLine);
              textBox->AppendText("BEFORE x = " + num1.ToString() + ", y = " + num2.ToString() + Environment::NewLine);
              Swap(num1, num2);
              var1 = num1;
              var2 = num2;
              textBox->AppendText("AFTER  x = " + num1.ToString() + ", y = " + num2.ToString() + Environment::NewLine);
              What we do here is, we allocate 2 int variables on the stack, initialize them with the values of the heap variables, swap them and store the resulting values back to the heap variables.
              I wouldn't go in details here about the tracking types (maybe in some other thread) as the post is large as it is without it, but i hope you understand what were you doing wrong in your approach and how to work around the problem.

              Cheers

              Comment

              • BahatiSiD
                New Member
                • Oct 2008
                • 9

                #8
                That seems about right!

                As it stands I’m writing my code in a ref class which is Form1 and when I declare an int outside of a function (which is then a member function of Form1) it's just a member variable of a ref class so I guess it's on the heap too.

                This clearly isn't the way to go, so it's back to the drawing board for me. :)

                Can someone point me in the direction of a fairly comprehensive managed c++ windows forms sample project? I’ve looked at the examples provided with VS2008 but I’m having trouble compiling them.

                Comment

                • eric2008
                  New Member
                  • Dec 2009
                  • 1

                  #9
                  pass by reference

                  pass by reference is different in .NET C++, and there is definitely an easy way to do. I've come across the answer before, but forgot.

                  I know this isn't a direct answer to the question....but I think it might clear matters up.

                  Comment

                  Working...