How to Explain C++ Pointers to a C#/Java Developer

How do you explain C++ pointers to a C#/Java developer?

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.

C pointers in C#

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.

When to use pointers in C#/.NET?

When is this needed? Under what circumstances does using pointers becomes inevitable?

When the net cost of a managed, safe solution is unacceptable but the net cost of an unsafe solution is acceptable. You can determine the net cost or net benefit by subtracting the total benefits from the total costs. The benefits of an unsafe solution are things like "no time wasted on unnecessary runtime checks to ensure correctness"; the costs are (1) having to write code that is safe even with the managed safety system turned off, and (2) having to deal with potentially making the garbage collector less efficient, because it cannot move around memory that has an unmanaged pointer into it.

Or, if you are the person writing the marshalling layer.

Is it only for performance reasons?

It seems perverse to use pointers in a managed language for reasons other than performance.

You can use the methods in the Marshal class to deal with interoperating with unmanaged code in the vast majority of cases. (There might be a few cases in which it is difficult or impossible to use the marshalling gear to solve an interop problem, but I don't know of any.)

Of course, as I said, if you are the person writing the Marshal class then obviously you don't get to use the marshalling layer to solve your problem. In that case you'd need to implement it using pointers.

Why does C# expose this functionality through an unsafe context, and remove all of the managed advantages from it?

Those managed advantages come with performance costs. For example, every time you ask an array for its tenth element, the runtime needs to do a check to see if there is a tenth element, and throw an exception if there isn't. With pointers that runtime cost is eliminated.

The corresponding developer cost is that if you do it wrong then you get to deal with memory corruption bugs that formats your hard disk and crashes your process an hour later rather than dealing with a nice clean exception at the point of the error.

Is it possible to use pointers without losing any advantages of managed environment, theoretically?

By "advantages" I assume you mean advantages like garbage collection, type safety and referential integrity. Thus your question is essentially "is it in theory possible to turn off the safety system but still get the benefits of the safety system being turned on?" No, clearly it is not. If you turn off that safety system because you don't like how expensive it is then you don't get the benefits of it being on!

What is the real difference between Pointers and References?

It's all just indirection: The ability to not deal with data, but say "I'll direct you to some data, over there". You have the same concept in Java and C#, but only in reference format.

The key differences are that references are effectively immutable signposts - they always point to something. This is useful, and easy to understand, but less flexible than the C pointer model. C pointers are signposts that you can happily rewrite. You know that the string you're looking for is next door to the string being pointed at? Well, just slightly alter the signpost.

This couples well with C's "close to the bone, low level knowledge required" approach. We know that a char* foo consists of a set of characters beginning at the location pointed to by the foo signpost. If we also know that the string is at least 10 characters long, we can change the signpost to (foo + 5) to point at then same string, but start half the length in.

This flexibility is useful when you know what you're doing, and death if you don't (where "know" is more than just "know the language", it's "know the exact state of the program"). Get it wrong, and your signpost is directing you off the edge of a cliff. References don't let you fiddle, so you're much more confident that you can follow them without risk (especially when coupled with rules like "A referenced object will never disappear", as in most Garbage collected languages).

C# - Unsafe and Pointers Basics

  1. You have an exception because you don't allocate memory for integers. Actually (int*)130 means that 130 is an address, which means p1 points to nowhere. You need to allocate memory to write and read values:
int v1 = 130, v2 = 45; // allocation
int* p1=&v1, p2; // or U can use stackalloc to allocate int:
// int* p1 = stackalloc int[1] { 130 }, p2;
*p1 = 50; // it's ok because we have already allocated memory for an integer,
// here we just overwrite the value.
p2 = &v2; // ok

//p2 = &130; // not ok.
//*p2 = 50; // not ok. You are trying to dereference null
//p2 = stackalloc int[1] { 45 }; // not ok, You can use a stackalloc expression only in a
// local variable declaration to initialize the variable.

  1. Starting in C# 9, you don't have to explicitly include a Main method in a console application project. Instead, you can use the top-level statements feature to minimize the code you have to write. In this case, the compiler generates a class and Main method entry point for the application.

  2. If You want to use unsafe features (pointers), you put an unsafe block or unsafe modifier on method/class/struct :) read more .
    Most of the time you don't want to use unsafe code, it won't give you performance (if you don't know what you're doing) but it will make your code less readable.

  3. You can't. Everything in C# is an object (nearly)(actually you can use static methods (but it's better not to overuse it)).

Is there pointer in C# like C++? Is it safe?

If you're implementing a tree structure in C# (or Java, or many other languages) you'd use references instead of pointers. NB. references in C++ are not the same as these references.

The usage is similar to pointers for the most part, but there are advantages like garbage collection.

class TreeNode
{
private TreeNode parent, firstChild, nextSibling;

public InsertChild(TreeNode newChild)
{
newChild.parent = this;
newChild.nextSibling = firstChild;
firstChild = newChild;
}
}

var root = new TreeNode();
var child1 = new TreeNode();
root.InsertChild(child1);

Points of interest:

  • No need to modify the type with * when declaring the members
  • No need to set them to null in a constructor (they're already null)
  • No special -> operator for member access
  • No need to write a destructor (although look up IDisposable)

Why C++ uses pointer for next node in linked list, but langauges like C# or Java use just the name of the class Node?

After reading the posted answers and other stackoverflow stuffs related to references and pointers like this one C++ references Vs C# references

This is what Makes more sense to me,

  • C# References are Managed references. But in C++ there is no such
    manged environment hence we need to allocate and carefully
    de-allocate the memory. In C# this will be manged automatically by
    GC. So it is recommended to use references where ever possible rather
    than directly using pointers.

  • Similar to C++ Pointers, C# can also hold nulls. C++ pointers hold
    address of a memory location, C# References holds the address of
    another object in the memory.

  • In C# we can use pointers only under unsafe scope, and in java there is no such pointer concepts.

Taking all this into account we can use references rather than pointers for programming languages that execute in a managed environment.

Feel free to edit if this answer can be further improved!

Learn C# to transition to C/C++?

Doubtful. C# is not significantly more C++-like than Java. It does support pointers in unsafe code, but beyond that I can't think of any reason it would make an especially good bridge from Java to C++. Also that is a feature I suspect more likely to be used by developers coming from the other direction. If you have other reasons for learning C# I say go for it, but for the purposes of transitioning more easily to C++, I'd say skip it.

is this good to have pointers in programming languages such as golang,C or C++?

Technically, all languages use pointers. When you create an instance of an object in Java or C# or Javascript and pass it to a method you are actually passing a pointer to the piece of memory that contains that object by which you will manipulate the data on that piece of memory. Imagine a language where you could not pass by reference. You wouldn't be able to do much, now would you? Whenever you pass by reference in any language, you're - in the most basic of terms - using glorified pointers.

What you probably mean, however, is "why expose pointers to people; they are so much more complicated", or something of that sort... And the answer is probably speed and tradition. Some of the fastest languages we have are C and C++... They've been around for a relatively long time. They are tried and true, and people know how to use them. Most software is based off of them in one way or another. Most operating systems are written in C or some variation thereof. Even other programming languages.

As for your Go example, we have already had a question on that..

What is the difference between passing by reference in Java and passing a pointer in C?

Neither Java nor C has pass-by-reference. They are both strictly pass-by-value.

Pass-by-reference semantics mean that when you change the value of the parameter in the method, the caller will see that change in the argument.

Now, you may be thinking: "But that's the case in Java! If I change an object during the method, the caller sees that change." The object isn't the parameter. The parameter is just the variable - and if you change the value of that variable, the caller won't see that. For example:

public void foo(Object x)
{
x = null;
}

public void caller()
{
Object y = new Object();
foo(y);
// y is still not null!
}

If the parameter were really passed by reference, y would be null afterwards. Instead, the value of y is just a reference, and that reference is passed by value. It's confusing because the word "reference" is in both terms, but they're different things.

You may want to look at my article about C# parameter passing to see what would be possible if Java did have pass-by-reference semantics, as C# does when (and only when) you use the ref keyword.

You may also want to look at the comments to my Stack Overflow answer related to the topic.



Related Topics



Leave a reply



Submit