結構變量作為方法的參數調用,在方法內部使用的“坑”你遇到過嗎?


很久沒有寫博了,今天一個同學在問結構變量的問題,問結構到底是傳遞值還是傳遞引用。查過MSDN的都知道,結構默認是傳遞值的,因此在方法內部,結構的值會被復制一份。但是對於結構數組,如果值還是要被復制一份,這個內存占用是不是很多了呢?
一般來說,數組參數傳遞的是引用,那么數組的元素呢?它是被復制的還是被引用的?如果結構數組的元素象結構變量那樣也是復制的,那么對於方法調用的內存占用問題,就得好好考慮下了。

MSDN看了半天,也討論了半天,感覺還是沒有動手實驗最有說服力,我們先定義一個結構體:

struct Point
    {
        public int X;
        public int Y;
        public Point(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }

定義2個方法,分別以傳值和傳引用的方式來調用結構變量:

        static void TestStruc(Point p)
        {
            p.X++;
            p.Y++;

        }

        static void TestStruc2(ref Point p)
        {
            p.X++;
            p.Y++;

        }

調用代碼:

            Point p = new Point(1, 2);
            TestStruc(p);
            Console.WriteLine("call by value Point X={0},Y={1}", p.X, p.Y);

            TestStruc2(ref p);
            Console.WriteLine("call by ref Point X={0},Y={1}", p.X, p.Y);

調用結果符合預期,以引用傳遞的結構變量,它的值被改變了:

Struct Pont(X,Y) Test:
call by value Point X=1,Y=2
call by ref Point X=2,Y=3

 

下面,試試結構數組,看有何不同:

        static void TestStrucArray2(ref Point[] arr)
        {
            Point p = arr[0];
            p.X++;
            p.Y++;

        }

調用代碼:

            Point[] arr = new Point[2];
            arr[0] = new Point(1, 2);
            arr[1] = new Point(3, 4);

            TestStrucArray(arr);
            Console.WriteLine("call by value Point[0]: X={0},Y={1}", arr[0].X, arr[0].Y);

結果:

call by value Point[0]: X=1,Y=2

方法內部對結果數組元素的改變無效,難道結構數組被復制了?

驚出一身冷汗!

改成引用參數的方式來試試,避免復制結構數組:

       static void TestStrucArray2(ref Point[] arr)
        {
            Point p = arr[0];
            p.X++;
            p.Y++;

        }

結果:

call by value Point[0]: X=1,Y=2
call by ref Point[0]: X=1,Y=2

引用方式數組還是被復制了?看來哪里有問題阿。

去掉用一個結構變量來引用結構數組的成員,直接操作結構數組的元素,來看看調用結果:

        static void TestStrucArray3( Point[] arr)
        {
            //Point p = arr[0];
            arr[0].X++;
            arr[0].Y++;

        }

        static void TestStrucArray4(ref Point[] arr)
        {
            arr[0].X++;
            arr[0].Y++;

        }

調用代碼:

            TestStrucArray4(ref arr);
            Console.WriteLine("call by ref Point[0] not use var : X={0},Y={1}", arr[0].X, arr[0].Y);
            arr[0].X = 1; arr[0].Y = 2;

            TestStrucArray3( arr);
            Console.WriteLine("call by var Point[0] not use var : X={0},Y={1}", arr[0].X, arr[0].Y);

 

結果:

call by ref Point[0] not use var : X=2,Y=3
call by var Point[0] not use var : X=2,Y=3

直接操作結構數組的元素,元素的值被改變了,證明結構數組沒有復制數組元素的值,依然是對數組的引用,上面的問題虛驚一場。

我們對比下前后不同的代碼,發現TestStrucArray2 僅僅多了一行代碼:

       static void TestStrucArray2(ref Point[] arr)
        {
            Point p = arr[0];             p.X++;
            p.Y++;

        }

這說明,定義一個結構變量,讓另外一個結構變量的值賦值給它,等於是復制這個結構變量的值。

往往有時候,我們為了敲代碼方便,少寫幾個字,便定義一個臨時變量去引用原來的變量,而這種行為,對於操作結構變量,無疑是一個最大的坑,這個坑,你遇到過嗎?

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM