Sec*_*ret 36 c# pointers memory-management reference ref
我正在使用ref
并且不明白"它是像C/C++中的指针还是像C++中的引用一样?"
为什么我问你这么弱的问题?因为,当我正在阅读C#/.NET书籍,msdn或与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中那样的指针的子分配内存.那么ref
C#中的内容是什么?.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)
fre*_*low 22
ref
C#中的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)