我正在与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 中那样在外部为指针分配内存。那么什么是ref
在 C# 中? .NET VM 是否像普通 C/C++ 中的指针一样处理它?GC
为指针分配临时空间还是像 C++ 中的引用一样工作?做ref
仅适用于托管类型或值类型,例如bool, int
最好换一个unsafe
代码并以非托管风格传递指针?
在 C# 中,当您看到引用引用类型(即用class
代替struct
),那么你基本上总是通过指针处理对象。在 C++ 中,默认情况下所有内容都是值类型,而在 C# 中默认情况下所有内容都是引用类型。
当您在 C# 参数列表中说“ref”时,您真正所说的更像是“指向指针的指针”。您是说,在方法中,您想要替换的不是对象的内容,而是调用方法的代码中对对象本身的引用。
除非这是您的意图,否则您应该直接传递引用类型;在 C# 中,传递引用类型的成本很低(类似于在 C++ 中传递引用)。
学习/理解 C# 中值类型和引用类型之间的区别。它们是该语言中的一个主要概念,如果您尝试在 C# 领域使用 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;
}
对于 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);
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)