C#ref是C/C++中的指针还是C++中的引用?

Sec*_*ret 36 c# pointers memory-management reference ref

我正在使用ref并且不明白"它是像C/C++中的指针还是像C++中的引用一样?"

为什么我问你这么弱的问题?因为,当我正在阅读C#/.NET书籍,msdn或与C#开发人员交谈时,我会因以下原因而感到困惑:

  • C#开发人员建议不要ref在函数的参数中使用,e.g. ...(ref Type someObject)对他们没有好处,他们建议...(Type someObject),我真的不明白这个建议.我听到的原因:更好地处理对象的副本,然后将其用作返回值,而不是通过引用等来破坏内存...通常我会听到有关数据库连接对象的这种解释.就像我简单的C/C++体验一样,我真的不明白为什么使用引用是C#中的坏东西?我控制对象的生命及其内存分配/重新分配等...我在书籍和论坛中只读了建议it's bad, because you can corrupt your connection and cause a memory leak by a reference lose,所以我控制对象的生命,我可以手动控制我真正想要的东西,那为什么它不好?
  • 现在阅读不同的书籍并与不同的人交谈,我不清楚是ref一个指针(*)或像C++中的引用&吗?我记得C/C++中的指针总是分配一个大小为void*4字节的空间(有效大小取决于体系结构),其中主机是结构或变量的地址.在C++中,通过传递引用&,没有来自堆/堆栈的新分配,并且您在内存空间中使用已定义的对象,并且外部没有像在纯C中那样的指针的子分配内存.那么refC#中的内容是什么?.NET VM是否像普通C/C++中的指针一样处理它,它为指针GC分配临时空间,还是像C++中的引用那样工作?是否ref只能正确使用托管类型或者类似于值类型bool, int,更好地切换unsafe代码并以非托管样式传递指针?

Bil*_*eal 37

在C#中,当您看到引用引用类型的某些内容(即,使用class而不是声明的类型struct)时,您基本上总是通过指针处理该对象.在C++中,默认情况下一切都是值类型,而在C#中,默认情况下一切都是引用类型.

当你在C#参数列表中说"ref"时,你真正说的更像是"指向指针的指针".在方法中,您要说的是,在调用方法的代码中,您不想替换对象的内容,而是替换对象本身的引用.

除非那是你的意图,否则你应该直接传递引用类型; 在C#中,传递引用类型很便宜(类似于在C++中传递引用).

了解/理解C#中值类型和引用类型之间的区别.它们是该语言中的一个主要概念,如果您尝试在C#land中使用C++对象模型,那么事情将会非常混乱.

以下基本上是语义上等效的程序:

#include <iostream>

class AClass
{
    int anInteger;
public:
    AClass(int integer)
        : anInteger(integer)
    {  }

    int GetInteger() const
    {
        return anInteger;
    }

    void SetInteger(int toSet)
    {
        anInteger = toSet;
    }
};

struct StaticFunctions
{
    // C# doesn't have free functions, so I'll do similar in C++
    // Note that in real code you'd use a free function for this.

    static void FunctionTakingAReference(AClass *item)
    {
        item->SetInteger(4);
    }

    static void FunctionTakingAReferenceToAReference(AClass **item)
    {
        *item = new AClass(1729);
    }
};

int main()
{
    AClass* instanceOne = new AClass(6);
    StaticFunctions::FunctionTakingAReference(instanceOne);
    std::cout << instanceOne->GetInteger() << "\n";

    AClass* instanceTwo;
    StaticFunctions::FunctionTakingAReferenceToAReference(&instanceTwo);
    // Note that operator& behaves similar to the C# keyword "ref" at the call site.
    std::cout << instanceTwo->GetInteger() << "\n";

    // (Of course in real C++ you're using std::shared_ptr and std::unique_ptr instead,
    //  right? :) )
    delete instanceOne;
    delete instanceTwo;
}
Run Code Online (Sandbox Code Playgroud)

对于C#:

using System;

internal class AClass
{
    public AClass(int integer)
        : Integer(integer)
    {  }

    int Integer { get; set; }
}

internal static class StaticFunctions
{
    public static void FunctionTakingAReference(AClass item)
    {
        item.Integer = 4;
    }

    public static void FunctionTakingAReferenceToAReference(ref AClass item)
    {
        item = new AClass(1729);
    }
}

public static class Program
{
    public static void main()
    {
        AClass instanceOne = new AClass(6);
        StaticFunctions.FunctionTakingAReference(instanceOne);
        Console.WriteLine(instanceOne.Integer);

        AClass instanceTwo  = new AClass(1234); // C# forces me to assign this before
                                                // it can be passed. Use "out" instead of
                                                // "ref" and that requirement goes away.
        StaticFunctions.FunctionTakingAReferenceToAReference(ref instanceTwo);
        Console.WriteLine(instanceTwo.Integer);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Oleg:是的.和不.如果C#中的项实际上是一个值类型(即,被声明为`struct`),那么`ref`只是一个间接.否则就是两个. (3认同)
  • 值得区分的是,ref是(十分之九)对类参数没有用-但是当使用值类型时,ref int x确实有所作为。 (2认同)

fre*_*low 22

refC#中的A 等同于C++引用:

  • 他们的意图是传递参考
  • 没有空引用
  • 没有未初始化的参考文献
  • 你不能重新引用引用
  • 拼写引用时,实际上表示引用的变量

一些C++代码:

void foo(int& x)
{
    x = 42;
}
// ...
int answer = 0;
foo(answer);
Run Code Online (Sandbox Code Playgroud)

等价的C#代码:

void foo(ref int x)
{
    x = 42;
}
// ...
int answer = 0;
foo(ref answer);
Run Code Online (Sandbox Code Playgroud)

  • 关于引用类型的`ref`没有什么特别之处.C++等价物是对指针的引用:`T*&`. (8认同)