码迷,mamicode.com
首页 > 编程语言 > 详细

C#与C++参数传递方式对比.

时间:2015-02-10 01:46:55      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:

  这几天在看C++标准,其中看到C++引用,用于函数传递参数要比之前传递指针安全,方便.所以想到把C#里相关概念拿来比较下.

  如下是在C#的测试代码:

技术分享
    public class Book
    {
        public string Name { get; set; }
        public int Id { get; set; }
    }

    public struct StructBook
    {
        public string Name { get; set; }
        public int Id { get; set; }
    }

    class Program
    {
        static void testValue(StructBook book)
        {
            book.Id = 1;
            book.Name = "n1";
        }

        static void testPtr(Book book)
        {
            book.Id = 2;
            book.Name = "n2";
            book = new Book();
            book.Id = 3;
            book.Name = "n3";
        }

        static void testRef(ref StructBook book)
        {
            book.Id = 4;
            book.Name = "n4";
            //book = new StructBook();
            //book.Id = 5;
            //book.Name = "n5";
            var xx = new StructBook();
            xx.Id = 5;
            xx.Name = "n5";
            book = xx;
        }

        static void testPtrRef(ref Book book)
        {
            book.Id = 6;
            book.Name = "n6";
            book = new Book();
            book.Id = 7;
            book.Name = "n7";
        }

        static void Main(string[] args)
        {
            StructBook sutbook = new StructBook();
            sutbook.Id = 0;
            sutbook.Name = "n0";

            Console.WriteLine("----value:");
            testValue(sutbook);
            Console.WriteLine(sutbook.Id);
            Console.WriteLine(sutbook.Name);

            Book book = new Book();
            book.Id = sutbook.Id;
            book.Name = sutbook.Name;
            Console.WriteLine("----reference value:");
            testPtr(book);
            Console.WriteLine(book.Id);
            Console.WriteLine(book.Name);

            sutbook.Id = book.Id;
            sutbook.Name = book.Name;
            Console.WriteLine("----value reference:");
            testRef(ref sutbook);
            Console.WriteLine(sutbook.Id);
            Console.WriteLine(sutbook.Name);

            book.Id = sutbook.Id;
            book.Name = sutbook.Name;
            Console.WriteLine("----reference reference:");
            testPtrRef(ref book);
            Console.WriteLine(book.Id);
            Console.WriteLine(book.Name);

            Console.Read();
        }
    }
参数传递

  上面主要演示C#中值传递与引用传递二种类型(值类型与引用类型)的不同.先看一下运行结果.

技术分享

  结果没什么好说的,差不多是被大家讲烂了的.简单来说,C#里默认全是值传递,值传递就是在函数内生成一份临时变量,对临时变量的修改不会影响本身.不同的值类型传递的是本身,而引用类型传递的是他引用.对应的结果就是上面的testPtr与testRef.一种是值类型,修改的是临时变量,在函数调用外是不变的.另外是引用类型,如果是修改引用里的值,这是可以的,而如果修改的是引用本身(这个是值传递的临时变量),就是testPtr里的book = new Book();这个是修改是影响不到函数外部的.

  至于testRef与testPtrRef,都属性引用传递,那么他传递的就是他本身,在函数内的修改都会直接修改他本身,都会影响函数外面.

  我们对应上面几个函数,在C++中,也增加相应的一些方法,大家可以看到一些相同与不同之处.

技术分享
using namespace std;

class Book
{

public:
    string name;
    int id;

    Book()
    {
        cout << "Create new Book: " << this << endl;
    }

    ~Book()
    {
        cout << "Delete Book in: " << this << endl;
    }

    //void operator = (const Book& book)
    //{

    //}

    string(iName)()
    {
        return name;
    }
};
void testValue(Book book)
{
    cout << "temp address:" << &book << endl;
    book.id = 1;
    book.name = "n1";
}

void testPtr(Book* book)
{
    book->id = 2;
    book->name = "n2";
    cout << "old address:" << book << endl;
    book = new Book();
    cout << "new address:" << book << endl;
    book->id = 3;
    book->name = "n3";
    delete book;
}

void testRef(Book& book)
{
    book.id = 4;
    book.name = "n4";
    cout << "old address:" << &book << endl;
    auto xx = Book();
    xx.id = 5;
    xx.name = "n5";
    //这句话会调用 = 操作符.并没有发生地址操作.
    //所以后面的删除的临时变量不会对book本身有影响
    book = xx;
    cout << "new address:" << &book << endl;
    
    //内存分配的位置不管是在堆还上栈上不影响结果
    //auto nb = new Book();
    //nb->id = 55;
    //nb->name = "n55";
    //cout << "old value:" << &book << endl;
    //book = *nb;
    //cout << "new value:" << &book << endl;
    //delete nb;
}

void testPtrRef(Book*& book)
{
    book->id = 6;
    book->name = "n6";
    auto xx = new Book();
    xx->id = 7;
    xx->name = "n7";

    cout << "old address:" << book << endl;
    delete book;
    book = xx;
    cout << "new address:" << book << endl;
}

void test19()
{
    auto xb = new Book();
    xb->id = 0;
    xb->name = "n0";

    cout << "----value:" << endl;
    testValue(*xb);
    cout << xb->id << endl;
    cout << xb->name << endl;

    cout << "----pointer value:" << endl;
    testPtr(xb);
    cout << xb->id << endl;
    cout << xb->name << endl;

    cout << "----reference value:" << endl;
    testRef(*xb);
    cout << xb->id << endl;
    cout << xb->name << endl;

    cout << "----pointer reference:" << endl;
    testPtrRef(xb);
    cout << xb->id << endl;
    cout << xb->name << endl;

    delete xb;
}
C++ 函数传递

  技术分享

  我们可以看到与C#中相似的结果.在C++中,主要是值传递,指针传递,引用传递.指针传递也可以归到值传递中,因为指针传递的指针也是要生成临时指针.就表现的现象来说,C++中的值传递和C#的值传递值类型比较相似,C++中的指针传递和C#中的值传递引用类型比较相似,C++中的指针引用传递和C#的引用传递(包含值类型与引用类型)比较相似.

  C#中,结构是值类型,类是引用类型,而C++中,结构与类可以说没有区别,所以上面比对中,C++的传递方式要对比C#的传递方式在类型方式,还有上面比对中,我没说C++的引用传递和C#的什么比较像,只说C++中的指针引用传递和C#的引用传递比较像.那么C++的单独引用传递和C#的有那些不同.

  C++中,testValue里我们可以看到,book的地址变了,说明和C#一样,book是临时变量,在testValue完成后,直接调用析构函数删除临时变量.

  在testPtr中,我们可以看到book在new后,book是指向了新的地址,但是在外部调用显示book时,还是前面2与n2,这里delete book有和没有,结果是一样的,只是会有内存泄漏.这个的表现和C#值传递引用类型一样,在重新new后,对book所做的更改都无效,因为指针传递说到底还是值传递,传递的是地址,就是说,这个在testPtr会重新生成一份,但是他的指向与原变量一样.所以前面针对id与name的设置都会更新到函数外部,但是这个临时变量重新new后,他就已经和main里的book所指向的位置不一样,在家可以对比看下输出.我们通过这个也能更容易理解C#值传递引用类型内部发生的情况.

  而在C++的testRef中,虽然结果和C#的testRef一样,但是又可以说完全不是一回事.在C++,引用有比较严格的规定,比如引用初始化后,就不能再修改引用指向的对象.可以看输出结果里的地址的对比.而C#中的引用传递的值是可以重新修改指向的对象.具体可看传递引用类型参数(C# 编程指南).C++的引用像是* const,或是说加强限定的指针与一些语法糖的组合.至于结果显示是n5与5,主要是默认的赋值操作引起的,我们可以在Book类里重新定义赋值操作,什么都不做,就可以看到结果是4与n4了.

  在testPtrRef,我们传递指针的引用过去,通过输出结果上的地址显示,我们可以看到我们在函数内重新指向新的位置,改动能带到函数外.当然指针的指针也能做到这个效果.就和前面说的一样,引用应是一种特殊的指针表示方式,引用能做的到,指针也能做到,反之就不一定了.同时我们也可以猜测C#中,引用类型当值传递时,相当于默认加上指针,而用引用传递时,相当于有个二级指针.  

  下面是原来看过几道测试题,最后一个如何具体化?

技术分享
//float(*(*f)(float, float))(float);
void test7()
{
    float(**a)[10];//float 数组 指针 指针
    float(*aa)[10]; //float 数组 指针
    float aaa[10];
    aa = &aaa;
    a = &aa;
    aaa[0] = 4;
    cout << ***a << endl;

    float*(*b)[10];//float* 数组 指针
    float* bb[10];//指针数组
    bb[0] = new float[2];
    b = &bb;
    bb[0][0] = 5;
    cout << ***b << endl;

    float(*c[10])();
    c[0] = [](){return 6.0f; };
    cout << (**c)() << endl;

    float*((*d)[10]);//float* 数组 指针
    float*(dd[10]);
    dd[0] = new float(7);
    d = &dd;
    dd[0][0] = 7.0f;
    cout << ***d << endl;

    float(*e)();
    e = [](){ return 8.0f; };
    cout << e() << endl;

    //如何具体化.
    float(*(*f)(float, float))(float);
    auto ff = fvv;
}
View Code

 

C#与C++参数传递方式对比.

标签:

原文地址:http://www.cnblogs.com/zhouxin/p/4281796.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!