如题,我同样使用一个对象给另一个对象赋值
发现在C#中两个对象被“关联”起来了
而在C++中却没有,似乎在c#中对象名是指针,而c++中对象名是内存的区域
这是我的疑惑,下面是我测试的代码,请大家分析一下using System;
using System.Collections.Generic;
using System.Text;namespace StructTest
{
    class aa //测试用的类
    {
        public int a;
    }    class Program
    {
        static void Main(string[] args)
        {
            aa test1 = new aa();
            aa test2 = new aa();
            test1.a = 123;
            test2.a = 456;            Console.WriteLine("test1  " + test1.a);
            Console.WriteLine("test2  " + test2.a);
            test1 = test2;// 关键是此处
            Console.WriteLine("test1  " + test1.a);
            Console.WriteLine("test2  " + test2.a);            test2.a = 789;// 给test2赋值,发现test1也变了
            Console.WriteLine("test1  " + test1.a);
            Console.WriteLine("test2  " + test2.a);
            Console.ReadLine();
        }
    }}
// adfasdf.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <afx.h>
#include <iostream>
using namespace std;class aa  // 同样是测试用的类
{
public:
int a;};
int main(int argc, char* argv[])
{
int dddd;//没什么用就是让控制台程序停下来看结果 aa test1;
aa test2;
test1.a=123;
test2.a=456; cout<<"test1.a    "<<test1.a<<endl;
cout<<"test2.a    "<<test2.a<<endl; test1=test2;  // 此处赋值 cout<<"test1.a    "<<test1.a<<endl;
cout<<"test2.a    "<<test2.a<<endl;

test2.a=789;  // 对test2赋值,但是test1并没有跟着变
cout<<"test1.a    "<<test1.a<<endl;
cout<<"test2.a    "<<test2.a<<endl;
cin >> dddd;
return 0;
}

解决方案 »

  1.   

    C++是用的拷贝构造函数的技术,你的C++代码没有显式的声明一个拷贝构造函数,编译器就生成一个默认的拷贝构造函数,目的是将对象里所有的类成员赋值给被赋值的对象。如果你将c++中的对象声明成指针形式的话,那便和C#的情况是一样的了,本身原理是一样的.还有就是别忘了C++中的指针指向的对象不用的要释放~ 希望你能理解,建议你去看看c++书中拷贝构造函数的章节,可以帮助你加深理解其中原理
      

  2.   

    .net类型分为两种:值类型和引用类型.
    对应到C#就是struct和class
    一个引用类型的变量你可以看做是指向这个类型的一个指针.
    例如:
    Form frm = new Form();
    里的frm你可以看做是指向一个窗体实例的指针(事实上是一个Handle).
    引用类型实例的实际内存分配则是在托管堆中.而值类型不同,当你运行
    Point pt=new Point();
    时pt则是实实在在的在栈上开辟了sizeof (Point)大小的
    空间.而运行
    Point pt2 = pt;
    则是把pt的内容完整的复制到pt2中而不是赋个指针了事.LZ有兴趣可以去啃啃CLI via C#或者CLI via C++/CLI
      

  3.   

    1.C#中: test1=test2;因为test1是引用类型,堆栈(stack)上会给这个引用分配存储空间,但是只是存放的该对象的引用地址,引用地址指向托管堆(heap)中该对象的实体(通俗的理解就是两个引用地址指向同一个值)C#中 test1 = test2 表示设定两个不同(因为堆栈中其引用地址不同)的对象(实例化自同一个类)的实体指向了托管堆中同一实体,改变其中一个即等于改变了另外一个.
    这就是为什么:      test2.a = 789;// 给test2赋值,发现test1也变了 如果是两个Int类型的变量就不会了.
    因为int是值类型,其是直接放置在堆栈上的两个不同的地方,不会再有引用地址指向到托管堆中.
    所以,任意一个的改变只会影响自己.int i = 1;
    int j = 100;
    j = i;  //此时 i = 1 , j = 1
    j = 100; //此时 i = 1 , j = 1002.C\C++中: test1=test2;
    个人对C\C++了解不多(VB转VB.NET,C#的),但原理应该差不多. 
    test1=test2; 实际上只是单纯的传值而已.就相当于把test2的值COPY到test1. 两个的值还是指向不同的地方.
    而如果申明成这样就不同了,就会跟.NET一样aa *test1; 
    aa *test2;
      

  4.   

    再来个VB版的例子解释VarPtr 获取变量的内存地址. 
    ObjPtr:返回任何对象变量引用的地址 
    Private Sub Command1_Click()
    Dim A As Class1, B As Class1, C As Class1
    Set A = New Class1
    Set B = New Class1
    Set C = New Class1MsgBox ("A:" & VarPtr(A) & vbCrLf & _
                    "B:" & VarPtr(B) & vbCrLf & _
                    "C:" & VarPtr(C) & vbCrLf)
    End Sub
    (2)关于Set C= A 以及 SET C = NEW CLASS1的区别代码如下: 
    Option ExplicitPrivate Sub Command1_Click()
    Dim A As Class1, B As Class1, C As Class1
    Set A = New Class1
    Set B = New Class1
    Set C = AMsgBox ("A:" & VarPtr(A) & vbCrLf & _
                    "B:" & VarPtr(B) & vbCrLf & _
                    "C:" & VarPtr(C) & vbCrLf)MsgBox ("A:" & ObjPtr(A) & vbCrLf & _
                    "B:" & ObjPtr(B) & vbCrLf & _
                    "C:" & ObjPtr(C) & vbCrLf)
                    
    A.Value = 100
    MsgBox ("C.Value:" & C.Value)
    C.Value = 99
    MsgBox ("A.Value:" & A.Value)Set C = BMsgBox ("A:" & VarPtr(A) & vbCrLf & _
                    "B:" & VarPtr(B) & vbCrLf & _
                    "C:" & VarPtr(C) & vbCrLf)MsgBox ("A:" & ObjPtr(A) & vbCrLf & _
                    "B:" & ObjPtr(B) & vbCrLf & _
                    "C:" & ObjPtr(C) & vbCrLf)
                    
    C.Value = 1
    MsgBox ("A.Value:" & A.Value)
    MsgBox ("B.Value:" & B.Value)
    End Sub
     把Class1也贴上 Option ExplicitPrivate value_ As IntegerProperty Get Value() As String
        Value = value_
    End PropertyProperty Let Value(ByVal NewValue As String)
        value_ = NewValue
    End Property