Is this function declaration in C#:
void foo(string mystring)
the same as this one in C:
void foo(char *)
i.e. In C#, does the called function receive a pointer behind the scenes?
In this specific instance, it is more like:
void foo(const char *);
.Net strings are immutable and passed by reference. However, in general C# receives a pointer or reference to an object behind the scenes.
There are pointers behind the scenes in C#, though they are more like C++'s smart pointers, so the raw pointers are encapsulated. A char* isn't really the same as System.String since a pointer to a char usually means the start of a character array, and a C# string is an object with a length field and a character array. The pointer points to the outer structure which points into something like a wchar_t array, so there's some indirection with a C# string and wider characters for Unicode support.
No. In C# (and all other .NET languages) the String is a first-class data type. It is not simply an array of characters. You can convert back and forth between them, but they do not behave the same. There are a number of string manipulation methods (like "Substring()" and "StartsWith") that are available to the String class, which don't apply to arrays in general, which an array of characters is simply an instance of.
Essentially, yes. In C#, string (actually System.String) is a reference type, so when foo() is called, it receives a pointer to the string in the heap.
For value types (int, double, etc.), the function receives a copy of the value. For other objects, it's a reference pointing to the original object.
Strings are special because they are immutable. Technically it means it will pass the reference, but in practice it will behave pretty much like a value type.
You can force value types to pass a reference by using the ref keyword:
public void Foo(ref int value) { value = 12 }
public void Bar()
{
int val = 3;
Foo(ref val);
// val == 12
}
no in c# string is unicode.
in c# it is not called a pointer, but a reference.
If you mean - will the method be allowed to access the contents of the character space, the answer is yes.
Yes, because a string is of dynamic size, so there must be heap memory behind the scenes
However they are NOT the same.
in c the pointer points to a string that may also be used elsewhere, so changing it will effect those other places.
Anything that is not a "value type", which essentially covers enums, booleans, and built-in numeric types, will be passed "by reference", which is arguably the same as the C/C++ mechanism of passing by reference or pointer. Syntactically and semantically it is essentially identical to C/C++ passing by reference.
Note, however, that in C# strings are immutable, so even though it is passed by reference you can't edit the string without creating a new one.
Also note that you can't pass an argument as "const" in C#, regardless whether it is a value type or a reference type.
While those are indeed equivalent in a semantic sense (i.e. the code is doing something with a string), C#, like Java, keeps pointers completely out of its everyday use, relegating them to areas such as transitions to native OS functions - even then, there are framework classes which wrap those up nicely, such as SafeFileHandle.
Long story short, don't go out of your way thinking of pointers in C#.
As far as I know, all classes in C# (not sure about the others) are reference types.
Related
I'm aware that Pinnable<T> is an internal class used by the methods in the new Unsafe class, and it's not meant to be used anywhere else other than in that class. This question is not about something practical, but it's just to understand why it's been designed like this and to learn a bit more about the language and its various "tricks" like this one.
As a recap, the Pinnable<T> class is defined here, and it looks like this:
[StructLayout(LayoutKind.Sequential)]
internal sealed class Pinnable<T>
{
public T Data;
}
And it's mainly used in the Span<T>.DangerousCreate method, here:
public static Span<T> DangerousCreate(object obj, ref T objectData, int length)
{
Pinnable<T> pinnable = Unsafe.As<Pinnable<T>>(obj);
IntPtr byteOffset = Unsafe.ByteOffset<T>(ref pinnable.Data, ref objectData);
return new Span<T>(pinnable, byteOffset, length);
}
The reason for Pinnable<T> being that it's used to keep track of the original object, in case the Span<T> instance was created by one (instead of a native pointer).
Given that reference type doesn't matter when pinning a reference (fixing both a ref T and Unsafe.As<T, byte>(ref T) works the same), is there a specific reason why the Pinnable<T> class was made generic? The original design in DotNetCross here in fact had a Pinnable class with just a single byte field, and it worked just the same. Is there any reason why using a generic class in this case would be an advantage, other than avoiding to cast the reference time when writing/reading/returning it?
Is there any other way, other than this unsafe-cast done with Unsafe.As, to get a reference to an object (I mean a reference to the object contents, otherwise it'd be the same as any variable of a class type)? I mean, any way to get a reference (which should basically have the same address of the actual object variable in the first place, right?) to an object without having to pass through some custom defined secondary class.
First of all, the Struct in [StructLayout(LayoutKind.Sequential)] doesn't mean that it is only valid for structs, it means the layout of the actual structure of the fields in memory, be it in a class or in a value type. This controls the actual runtime layout of the data, not just how the type would marshal to unmanaged code. The Sequential is important because without it, the runtime is pretty much free to store the memory however it sees fit, which means that Data may have some padding before it.
From what I understand about the implementation, the reason for Pinnable is to allow creating an instance of Span to a memory that may be moved by the GC, without having to pin the object first. If you don't use actual pointers and just references, nothing at all will need to be pinned.
I have noticed that it was introduced in a commit with a description saying it made Span more "portable" (a bold word for something that does a lot of unsafe things). I can't think of any other reason than something related to alignment for why it is generic. I suppose representing a T in terms of an offset from another T is better than as an offset from a byte. It may happen that the type of the first field may play a role in its actual address, even if the type was marked with LayoutKind.Sequential.
A reference to an object is different from an interior reference to an object (a reference to its data). It is implementation defined, but in .NET Framework, an instance of any class (or a boxed value type) starts with a header consisting of a sync block (for lock) and a pointer to the method table, a.k.a. the type of the object. On 32-bit, the header is 8 bytes, but the actual pointer points to the pointer to the method table (for performance reasons, getting the type happens more often than locking an object).
One but not portable way of getting the pointer to the start of the data is therefore casting the object reference to a pointer and adding 4 bytes to it. There the first field should start.
Another way I can think of is utilising GCHandle.AddrOfPinnedObject. It is commonly used for accessing array or string data, but it works for other objects:
[StructLayout(LayoutKind.Sequential)]
class Obj
{
public int A;
}
var obj = new Obj();
var gc = GCHandle.Alloc(obj, GCHandleType.Pinned);
IntPtr interior = gc.AddrOfPinnedObject();
Marshal.WriteInt32(interior, 0, 16);
Console.WriteLine(obj.A);
I think this actually is quite portable, but still needs to pin the object (there is InternalAddrOfPinnedObject defined in GCHandle, but even if that doesn't check whether the handle is actually pinned, the returned value may not be valid if it was used on a non-pinned object).
Still, the technique Span uses seems like the most portable way of doing that, since a lot of the underlying work is done in pure CIL (like reference arithmetics).
I am learning the basics of C++, coming from the .NET world (C#).
One topic i found interesting was the const keyword and its usage with pointers (const pointer/pointer to const).
I'd like to know if there's any C# language equivalent of the const pointer/pointer to const that C++ has?
(I know C# doesn't have pointers, i am considering references to be the pointer-like types in C#).
Also, out of interest, if there's no such equivalent, what were the decisions behind not including such a feature?
There is no direct equivalent to passing references as 'const' in C#, but there are alternative ways to accomplish its purpose. The most common way to do this is to make your reference class either completely immutable (once constructed, its state should never change) or pass it as an immutable public interface. The latter is the closest to the intention of the 'const' parameter contract (I'm giving you a reference to something so you can use it, but I'm asking you not to change it.) A poorly-behaved client could 'cast away' the public interface to a mutable form, of course, but it still makes the intention clear. You could 'cast away' const in C++, as well, thought this was rarely a good idea.
One other thing in C++ is that you would often prefer to pass as const when you knew that the lifetime of the reference you were passing was limited in scope. C++ often follows the pattern where objects are created and destroyed on the stack within method scope, so any references to those objects should not be persisted outside that scope (since using them after they fall out of scope could cause really nasty stack corruption crashes.) A const reference should not be mutated, so it's a strong hint that storing it somewhere to reference later would be a bad idea. A method with const parameters is promising that it's safe to pass these scoped references. Since C# never allows storing references to objects on the stack (outside of parameters), this is less of a concern.
The concept of constant objects (i.e. readonly) in C# (or Java for that matter) corresponds approximately to object *const in C++, i.e. a constant pointer to a non-constant object.
There are several reasons for it - for one specifying const correctly and making it useful in the language is quite hard. Taking c++ as an example, you have to define lots of methods twice with only small changes to the signature, there's const_cast, the fact that const is only applied shallow, etc.
So C# went for the easy solution to make the language simpler - D went the other way with transitive const correctness, etc. as I understand it (never written a single line in D, so take that with a grain of salt).
The usual solution in C#/Java is to have immutable classes, possibly using a builder pattern, or a simple wrapper that prohibits changes (e.g. all the unmodifiable collections that wrap another collection and throw exceptions for the mutating methods like add).
8,000,000 years later, but C# 7.2 uses the "in" keyword which is sort of like const. It tells the compiler to pass a struct or primitive variable by reference (like ref or out) but the method WILL NOT modify the variable.
public void DoSomething(in int variable){
//Whatever
}
is functionally equivalent to C++'s
void Foo::DoSomething(int& const variable){
//Whatever
}
or arguably even
void Foo::DoSomething(int const * const variable){
//Whatever
}
The main reason for doing this in C#, according to MSDN, is to tell the compiler that it can pass the variable by reference since it won't be modified. This allows for potentially better performance when passing large structs
Regarding constant pointers, see this answer: Difference between const. pointer and reference?
In other words, a reference in C++ is very similar to a const pointer for most applications. However, a reference in C# is closer to a pointer in C++ regarding how they can be used.
Reference objects passed as arguments to methods in C# can be reinstantiated (say, from Object Instance A to Object Instance B), however the B's lifetime is only within the method scope and is disposed of once returned to the caller (since the pointer itself is passed by value) and the caller's reference is always to A. In this sense, you can freely pass around references in C# and know that they cannot be made to point to different objects (unless ref/out keywords are used).
C# example -
class Foo
{
//Stateful field
public int x;
//Constructor
public Foo()
{
x = 6;
}
}
public class Program
{
public static void Main()
{
var foo = new Foo();
foo.x = 8;
VarTestField(foo);
Console.WriteLine(foo.x);
RefTestField(ref foo);
Console.WriteLine(foo.x);
}
//Object passed by reference, pointer passed by value
static void VarTestField(Foo whatever){
whatever = new Foo();
}
//Object passed by reference, pointer passed by reference
static void RefTestField(ref Foo whatever){
whatever = new Foo();
}
}
Output:
8
6
So no, you cannot declare a constant pointer in C#. Still, using proven design patterns, algorithms, and OOP fundamentals wisely, along with the built in syntax of the language, you can achieve the desired behavior.
I'm porting a C++ library to C# and I've encountered some methods that have double* pointers as parameters. What's the best way to deal with this? Perhaps modify the calling code so that it's not passing pointers? I WOULD just wrap the code in an "unsafe" block and set the compiler's /unsafe flag, but I can't do that inside of the method signature.
Maybe uusing ref (or out) on parameters may be good enough, or if you need to handle an array of those use a double[].
Maybe post the method definition so that it gets clearer what you really need.
I'm assuming that you wish to use managed safe code
Depends on how the pointer is used. If it's used as an array inside your method then you'll need to pass an array to the method and therefor need to change the signature.
if it's used as a double and (re)assigned it again depends. Does the method have return type? if so using ref double might be the way to go. if the method doesn't have a return type return the value being assigned and let the caller passing to a local instead of passing by ref.
if the double* is used as a double and never assign simply pass as double.
Probably it translates to ref double or out double or double[]. Which it should be depends on the semantics of the code. C++ double* can actually mean a number of things.
It's highly unlikely that unsafe code is needed.
You could mark the function as unsafe and compile with the /unsafe flag:
private static unsafe void MyFunction(double *d)
See http://msdn.microsoft.com/en-us/library/chfa2zb8.aspx
Where you are passing pointers, you are simply changing the default pass-by-value mechanism to pass-by-reference, in which case, use the ref keyword:
public void SomeMethod(ref double val) { }
In which you need to ensure you specifiy ref when call it too:
SomeMethod(ref 12.0);
What you do will depend on how the pointer is being used. If the pointer is there so that the calling code can pass an array of doubles, then have the method accept a double[]. If the pointer is there so that the called code can modify the value of a double variable from the caller, then you have two choices:
Modify the semantics of the call in such a way that the double is a return value (this would be the way I'd suggest)
Declare the parameter as ref or out (depending on whether or not you want to guarantee that the called function will assign a value.
Don't just throw unsafe blocks around code so that you can continue to use pointers; unsafe should be used very sparingly (ideally not at all).
It depends on how the function uses the pointer. You don't really give enough info to give a solid answer, but I'll give it a shot anyway.
Normal C# code
If the code in the method is de-referencing the pointer and assigning a value, without doing any pointer arithmetic, then simply make the parameter an out parameter.
If the previous paragraph is true, and you don't already have a return value, simply modify the signature of the method to return a double.
If the code is not doing pointer arithmetic, but uses the value that already exists at the pointed location, as well as assigning it, then make the parameter a ref parameter.
If the code does no pointer arithmetic, uses the value, but doesn't assign it, then you should probably change it from a pointer to a plain double, and not make it ref or out.
If the implementation of the function is doing pointer arithmetic, then you'll need to build and pass some sort of indexable collection, such as one that implements IList or an array.
Alternatives to normal C# code
You could always opt to mark your code unsafe, too, and use pointers. That will probably be a lot more work than simple logical translations, but is more likely to maintain a similar performance profile.
You could also opt to use C++/CLI instead of C#. It is also a .Net langauge, and might be simpler (depending on your app) to integrate directly with the existing C++ code.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am a C#/Java developer trying to learn C++. As I try to learn the concept of pointers, I am struck with the thought that I must have dealt with this concept before. How can pointers be explained using only concepts that are familiar to a .NET or Java developer? Have I really never dealt with this, is it just hidden to me, or do I use it all the time without calling it that?
Java objects in C++
A Java object is the equivalent of a C++ shared pointer.
A C++ pointer is like a Java object without the garbage collection built in.
C++ objects.
C++ has three ways of allocating objects:
Static Storage Duration objects.
These are created at startup (before main) and die after main exits.
There are some technical caveats to that but that is the basics.
Automatic Storage Duration objects.
These are created when declared and destroyed when they go out of scope.
I believe these are like C# structs
Dynamic Storage Duration objects
These are created via new and the closest to a C#/Java object (AKA pointers)
Technically pointers need to be destroyed manually via delete. But this is considered bad practice and under normal situations they are put inside Automatic Storage Duration Objects (usually called smart pointers) that control their lifespan. When the smart pointer goes out of scope it is destroyed and its destructor can call delete on the pointer. Smart pointers can be though of as fine grain garbage collectors.
The closest to Java is the shared_ptr, this is a smart pointer that keeps a count of the number of users of the pointer and deletes it when nobody is using it.
You are "using pointers" all the time in C#, it's just hidden from you.
The best way I reckon to approach the problem is to think about the way a computer works. Forget all of the fancy stuff of .NET: you have the memory, which just holds byte values, and the processor, which just does things to these byte values.
The value of a given variable is stored in memory, so is associated with a memory address. Rather than having to use the memory address all the time, the compiler lets you read from it and write to it using a name.
Furthermore, you can choose to interpret a value as a memory address at which you wish to find another value. This is a pointer.
For example, lets say our memory contains the following values:
Address [0] [1] [2] [3] [4] [5] [6] [7]
Data 5 3 1 8 2 7 9 4
Let's define a variable, x, which the compiler has chosen to put at address 2. It can be seen that the value of x is 1.
Let's now define a pointer, p which the compiler has chosen to put at address 7. The value of p is 4. The value pointed to by p is the value at address 4, which is the value 2. Getting at the value is called dereferencing.
An important concept to note is that there is no such thing as a type as far as memory is concerned: there are just byte values. You can choose to interpret these byte values however you like. For example, dereferencing a char pointer will just get 1 byte representing an ASCII code, but dereferencing an int pointer may get 4 bytes making up a 32 bit value.
Looking at another example, you can create a string in C with the following code:
char *str = "hello, world!";
What that does is says the following:
Put aside some bytes in our stack frame for a variable, which we'll call str.
This variable will hold a memory address, which we wish to interpret as a character.
Copy the address of the first character of the string into the variable.
(The string "hello, world!" will be stored in the executable file and hence will be loaded into memory when the program loads)
If you were to look at the value of str you'd get an integer value which represents an address of the first character of the string. However, if we dereference the pointer (that is, look at what it's pointing to) we'll get the letter 'h'.
If you increment the pointer, str++;, it will now point to the next character. Note that pointer arithmetic is scaled. That means that when you do arithmetic on a pointer, the effect is multiplied by the size of the type it thinks it's pointing at. So assuming int is 4 bytes wide on your system, the following code will actually add 4 to the pointer:
int *ptr = get_me_an_int_ptr();
ptr++;
If you end up going past the end of the string, there's no telling what you'll be pointing at; but your program will still dutifully attempt to interpret it as a character, even if the value was actually supposed to represent an integer for example. You may well be trying to access memory which is not allocated to your program however, and your program will be killed by the operating system.
A final useful tip: arrays and pointer arithmetic are the same thing, it's just syntactic sugar. If you have a variable, char *array, then
array[5]
is completely equivalent to
*(array + 5)
A pointer is the address of an object.
Well, technically a pointer value is the address of an object. A pointer object is an object (variable, call it what you prefer) capable of storing a pointer value, just as an int object is an object capable of storing an integer value.
["Object" in C++ includes instances of class types, and also of built-in types (and arrays, etc). An int variable is an object in C++, if you don't like that then tough luck, because you have to live with it ;-)]
Pointers also have static type, telling the programmer and the compiler what type of object it's the address of.
What's an address? It's one of those 0x-things with numbers and letters it it that you might sometimes have seen in a debugger. For most architectures we can consider memory (RAM, to over-simplify) as a big sequence of bytes. An object is stored in a region of memory. The address of an object is the index of the first byte occupied by that object. So if you have the address, the hardware can get at whatever's stored in the object.
The consequences of using pointers are in some ways the same as the consequences of using references in Java and C# - you're referring to an object indirectly. So you can copy a pointer value around between function calls without having to copy the whole object. You can change an object via one pointer, and other bits of code with pointers to the same object will see the changes. Sharing immutable objects can save memory compared with lots of different objects all having their own copy of the same data that they all need.
C++ also has something it calls "references", which share these properties to do with indirection but are not the same as references in Java. Nor are they the same as pointers in C++ (that's another question).
"I am struck with the thought that I must have dealt with this concept before"
Not necessarily. Languages may be functionally equivalent, in the sense that they all compute the same functions as a Turing machine can compute, but that doesn't mean that every worthwhile concept in programming is explicitly present in every language.
If you wanted to simulate the C memory model in Java or C#, though, I suppose you'd create a very large array of bytes. Pointers would be indexes in the array. Loading an int from a pointer would involve taking 4 bytes starting at that index, and multiplying them by successive powers of 256 to get the total (as happens when you deserialize an int from a bytestream in Java). If that sounds like a ridiculous thing to do, then it's because you haven't dealt with the concept before, but nevertheless it's what your hardware has been doing all along in response to your Java and C# code[*]. If you didn't notice it, then it's because those languages did a good job of creating other abstractions for you to use instead.
Literally the closest the Java language comes to the "address of an object" is that the default hashCode in java.lang.Object is, according to the docs, "typically implemented by converting the internal address of the object into an integer". But in Java, you can't use an object's hashcode to access the object. You certainly can't add or subtract a small number to a hashcode in order to access memory within or in the vicinity of the original object. You can't make mistakes in which you think that your pointer refers to the object you intend it to, but actually it refers to some completely unrelated memory location whose value you're about to scribble all over. In C++ you can do all those things.
[*] well, not multiplying and adding 4 bytes to get an int, not even shifting and ORing, but "loading" an int from 4 bytes of memory.
References in C# act the same way as pointers in C++, without all the messy syntax.
Consider the following C# code:
public class A
{
public int x;
}
public void AnotherFunc(A a)
{
a.x = 2;
}
public void SomeFunc()
{
A a = new A();
a.x = 1;
AnotherFunc(a);
// a.x is now 2
}
Since classes are references types, we know that we are passing an existing instance of A to AnotherFunc (unlike value types, which are copied).
In C++, we use pointers to make this explicit:
class A
{
public:
int x;
};
void AnotherFunc(A* a) // notice we are pointing to an existing instance of A
{
a->x = 2;
}
void SomeFunc()
{
A a;
a.x = 1;
AnotherFunc(&a);
// a.x is now 2
}
"How can pointers be explained using only concepts that are familiar to a .NET or Java developer? "
I'd suggest that there are really two distinct things that need to be learnt.
The first is how to use pointers, and heap allocated memory, to solve specific problems. With an appropriate style, using shared_ptr<> for example, this can be done in a manner analogous to that of Java. A shared_ptr<> has a lot in common with a Java object handle.
Secondly, however, I would suggest that pointers in general are a fundamentally lower level concept that Java, and to a lesser extent C#, deliberately hides. To program in C++ without moving to that level will guarantee a host of problems. You need to think in terms of the underlying memory layout and think of pointers as literally pointers to specific pieces of storage.
To attempt to understand this lower level in terms of higher concepts would be an odd path to take.
Get two sheets of large format graph paper, some scissors and a friend to help you.
Each square on the sheets of paper represents one byte.
One sheet is the stack.
The other sheet is the heap. Give the heap to your friend - he is the memory manager.
You are going to pretend to be a C program and you'll need some memory. When running your program, cut out chunks from the stack and the heap to represent memory allocation.
Ready?
void main() {
int a; /* Take four bytes from the stack. */
int *b = malloc(sizeof(int)); /* Take four bytes from the heap. */
a = 1; /* Write on your first little bit of graph paper, WRITE IT! */
*b = 2; /* Get writing (on the other bit of paper) */
b = malloc(sizeof(int)); /* Take another four bytes from the heap.
Throw the first 'b' away. Do NOT give it
back to your friend */
free(b); /* Give the four bytes back to your friend */
*b = 3; /* Your friend must now kill you and bury the body */
} /* Give back the four bytes that were 'a' */
Try with some more complex programs.
Explain the difference between the stack and the heap and where objects go.
Value types such as structs (both C++ and C#) go on the stack. Reference types (class instances) get put on the heap. A pointer (or reference) points to the memory location on the heap for that specific instance.
Reference type is the key word. Using a pointer in C++ is like using ref keyword in C#.
Managed apps make working with this stuff easy so .NET devs are spared the hassle and confusion. Glad I don't do C anymore.
The key for me was to understand the way memory works. Variables are stored in memory. The places in which you can put variables in memory are numbered. A pointer is a variable that holds this number.
Any C# programmer that understands the semantic differences between classes and structs should be able to understand pointers. I.e., explaining in terms of value vs. reference semantics (in .NET terms) should get the point across; I wouldn't complicate things by trying to explain in terms of ref (or out).
In C#, all references to classes are roughly the equivalent to pointers in the C++ world. For value types (structs, ints, etc..) this is not the case.
C#:
void func1(string parameter)
void func2(int parameter)
C++:
void func1(string* parameter)
void func2(int parameter)
Passing a parameter using the ref keyword in C# is equivalent to passing a parameter by reference in C++.
C#:
void func1(ref string parameter)
void func2(ref int parameter)
C++:
void func1((string*)& parameter)
void func2(int& parameter)
If the parameter is a class, it would be like passing a pointer by reference.
I just made a Swap routine in C# like this:
static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
It does the same thing that this C++ code does:
void swap(int *d1, int *d2)
{
int temp=*d1;
*d1=*d2;
*d2=temp;
}
So are the ref and out keywords like pointers for C# without using unsafe code?
They're more limited. You can say ++ on a pointer, but not on a ref or out.
EDIT Some confusion in the comments, so to be absolutely clear: the point here is to compare with the capabilities of pointers. You can't perform the same operation as ptr++ on a ref/out, i.e. make it address an adjacent location in memory. It's true (but irrelevant here) that you can perform the equivalent of (*ptr)++, but that would be to compare it with the capabilities of values, not pointers.
It's a safe bet that they are internally just pointers, because the stack doesn't get moved and C# is carefully organised so that ref and out always refer to an active region of the stack.
EDIT To be absolutely clear again (if it wasn't already clear from the example below), the point here is not that ref/out can only point to the stack. It's that when it points to the stack, it is guaranteed by the language rules not to become a dangling pointer. This guarantee is necessary (and relevant/interesting here) because the stack just discards information in accordance with method call exits, with no checks to ensure that any referrers still exist.
Conversely when ref/out refers to objects in the GC heap it's no surprise that those objects are able to be kept alive as long as necessary: the GC heap is designed precisely for the purpose of retaining objects for any length of time required by their referrers, and provides pinning (see example below) to support situations where the object must not be moved by GC compacting.
If you ever play with interop in unsafe code, you will find that ref is very closely related to pointers. For example, if a COM interface is declared like this:
HRESULT Write(BYTE *pBuffer, UINT size);
The interop assembly will turn it into this:
void Write(ref byte pBuffer, uint size);
And you can do this to call it (I believe the COM interop stuff takes care of pinning the array):
byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);
In other words, ref to the first byte gets you access to all of it; it's apparently a pointer to the first byte.
Reference parameters in C# can be used to replace one use of pointers, yes. But not all.
Another common use for pointers is as a means for iterating over an array. Out/ref parameters can not do that, so no, they are not "the same as pointers".
ref and out are only used with function arguments to signify that the argument is to be passed by reference instead of value. In this sense, yes, they are somewhat like pointers in C++ (more like references actually). Read more about it in this article.
The nice thing about using out is that you're guaranteed that the item will be assigned a value -- you will get a compile error if not.
Actually, I'd compare them to C++ references rather than pointers. Pointers, in C++ and C, are a more general concept, and references will do what you want.
All of these are undoubtedly pointers under the covers, of course.
While comparisons are in the eye of the beholder...I say no. 'ref' changes the calling convention but not the type of the parameters. In your C++ example, d1 and d2 are of type int*. In C# they are still Int32's, they just happen to be passed by reference instead of by value.
By the way, your C++ code doesn't really swap its inputs in the traditional sense. Generalizing it like so:
template<typename T>
void swap(T *d1, T *d2)
{
T temp = *d1;
*d1 = *d2;
*d2 = temp;
}
...won't work unless all types T have copy constructors, and even then will be much more inefficient than swapping pointers.
The short answer is Yes (similar functionality, but not exactly the same mechanism).
As a side note, if you use FxCop to analyse your code, using out and ref will result in a "Microsoft.Design" error of "CA1045:DoNotPassTypesByReference."