Why links don't reset in C ++

C ++ links have two properties:

  • They always point to the same object.
  • They cannot be 0.

Pointers are opposite:

  • They can point to different objects.
  • They can be 0.

Why is there no "non-null, comparable reference or pointer" in C ++? I can’t come up with a good reason why links should not be transplants.

Edit: The question often arises because I usually use links when I want to make sure that the “association” (I avoid the words “link” or “pointer” here) is never invalid.

I don’t think I ever thought that "this ref always refers to the same object." If the links were reseatable, you can still get the current behavior as follows:

int i = 3; int& const j = i; 

This is already legal C ++, but pointless.

I repeat my question as follows:. What was the rationale for the link is an object construct? Why was it considered useful to have references always as the same object, and not just when declared as const? "

Cheers, Felix

+51
c ++ pointers reference language-design
Apr 08 '09 at 1:58
source share
17 answers

The reason C ++ does not allow reordering links is given in Struustrup "Design and Evolution of C ++":

It is not possible to change what the link refers to after initialization. That is, once a C ++ link is initialized, it cannot be referenced to another object later; it cannot be redefined. I had in the past bitten Algol68 links where r1=r2 can either assign via r1 to the object specified or assign a new task value to r1 (re-linking r1 ) depending on the type of r2 . I wanted to avoid such problems in C ++.

+68
Apr 08 '09 at 2:16
source share

In C ++, it is often said that "link is an object." In a sense, this is true: although links are treated as pointers when compiling the source code, the link is intended to indicate an object that is not copied when the function is called. Since links are not directly addressed (for example, links have no address and return the address of an object), it does not make sense semantically to reassign them. Moreover, C ++ already has pointers that handle the semantics of reinstallation.

+31
Apr 08 '09 at 2:05
source share

Because then you will not have a reseatable type, which cannot be 0. If you have not included 3 types of links / pointers. Which would just complicate the language for a very small gain (And then why not add the 4th type too? A nonreflective link, which could be 0?)

A better question might be, why do you want links to be saturated? If that were the case, it would make them less useful in many situations. This would make it harder for the compiler to parse aliases.

It seems that references to the root cause in Java or C # are reseatable because they do the work of pointers. They point to objects. They are not aliases for the object.

What should be the effect of the following:

 int i = 42; int& j = i; j = 43; 

In C ++ today, with irregular links, it's simple. j is an alias for i, and I end with a value of 43.

If the links were re-sorted, the third line will bind the link j to a different value. It will no longer be the pseudonym i, but instead will be the integer literal 43 (which, of course, is incorrect). Or perhaps a simpler (or at least syntactically correct) example:

 int i = 42; int k = 43; int& j = i; j = k; 

With cross-references. j will point to k after evaluating this code. With irrelevant C ++ references, j still points to i, and I am set to 43.

Bringing links in line with each other changes the semantics of the language. A link can no longer be an alias for another variable. Instead, it becomes a separate value type with its own assignment operator. And then one of the most common uses of links would be impossible. And nothing happened in return. Recently appeared functionality for links already existed in the form of pointers. So, now we have two ways to do the same, and it will not be possible to execute any links in the current C ++ language.

+14
Apr 08 '09 at 2:34
source share

The duplicate link will be functionally identical to the pointer.

Regarding invalidity: you cannot guarantee that such a “reference link” is not NULL at compile time, so any such test would have to be executed at run time. You can achieve this yourself by writing a smart pointer style class template that throws an exception when initializing or assigning NULL:

 struct null_pointer_exception { ... }; template<typename T> struct non_null_pointer { // No default ctor as it could only sensibly produce a NULL pointer non_null_pointer(T* p) : _p(p) { die_if_null(); } non_null_pointer(non_null_pointer const& nnp) : _p(nnp._p) {} non_null_pointer& operator=(T* p) { _p = p; die_if_null(); } non_null_pointer& operator=(non_null_pointer const& nnp) { _p = nnp._p; } T& operator*() { return *_p; } T const& operator*() const { return *_p; } T* operator->() { return _p; } // Allow implicit conversion to T* for convenience operator T*() const { return _p; } // You also need to implement operators for +, -, +=, -=, ++, -- private: T* _p; void die_if_null() const { if (!_p) { throw null_pointer_exception(); } } }; 

This can be useful sometimes - a function that accepts the non_null_pointer<int> parameter certainly passes more information to the caller than a function that takes int* .

+4
Apr 08 '09 at 2:50
source share

It would probably be less difficult to name C ++ links "aliases"? As others noted, references to C ++ should, however, be as the variables to which they refer, and not as a pointer / reference to a variable. Thus, I cannot think of why they should be reset.

when it comes to pointers, it often makes sense, allowing null as a value (and otherwise, you most likely want a reference). If you specifically want to prevent null storing, you can always specify your own type of smart pointer;)

+3
Apr 08 '09 at 2:16
source share

A link is not a pointer, it can be implemented as a pointer in the background, but its basic concept is not equivalent to a pointer. The link should look like this: *is* object to which it refers. Therefore, you cannot change it, and it cannot be NULL.

A pointer is just a variable that contains a memory address. The pointer itself has its own memory address, and inside this memory address it contains another memory address , which, as they say, is indicated. The link is not the same, it does not have its own address, and therefore, it cannot be changed to “hold” another address.

I think the parashift C ++ FAQ on links says better:

Important Note. Despite the fact that the link is often executed using the address in the base language assembly, please do not think of the link as a funny pointer to an object. A link is an object. This is not a pointer to an object or a copy of an object. This is an object.

and again in FAQ 8.5 :

Unlike a pointer, once a link is associated with an object, it cannot be "reset" to another object. the link itself is not an object (it does not have an identity; accepting the address, the link gives you the address of the referent; remember: the link is its referent).

+3
Apr 08 '09 at 2:35
source share

C ++ links can sometimes be forced equal to 0 with some compilers (this is just a bad idea for this *, and this violates the standard *).

 int &x = *((int*)0); // Illegal but some compilers accept it 

EDIT: according to various people who know the standard much better than me, the code above creates "undefined behavior". At least in some versions of GCC and Visual Studio, I saw this do the expected thing: the equivalent of setting a pointer to NULL (and throwing a NULL pointer when accessing it).

+2
Apr 08 '09 at 2:04
source share

Attentively, many of the answers here are a little fuzzy or even near the dot (for example, this is not because the links cannot be zero or similar, in fact you can easily build an example where the link is zero).

The real reason why link re-setting is not possible is pretty simple.

  • Pointers allow you to do two things: change the value behind the pointer (either using the -> or * operator), and change the pointer itself (direct = ). Example:

     int a; int * p = &a; 
    • Changing the value requires dereferencing: *p = 42;
    • Pointer change: p = 0;
  • Links allow you to change the value only. What for? Because there is no other syntax for expressing redial. Example:

     int a = 10; int b = 20; int & r = a; r = b; // re-set r to b, or set a to 20? 

In other words, it would be ambiguous if you were allowed to re-set the link. This is even more important when passing by reference:

 void foo(int & r) { int b = 20; r = b; // re-set r to a? or set a to 20? } void main() { int a = 10; foo(a); } 

Hope that helps :-)

+2
Feb 10 '15 at 15:20
source share

This is actually not an answer, but a workaround for this limitation.

Basically, when you try to “reset” the link, you are actually trying to use the same name to refer to the new value in the following context. In C ++, this can be achieved by entering a block area.

In jalf example

 int i = 42; int k = 43; int& j = i; //change i, or change j? j = k; 

if you want to change i, write it as described above. However, if you want to change the value of j to k , you can do this:

 int i = 42; int k = 43; int& j = i; //change i, or change j? //change j! { int& j = k; //do what ever with j new meaning } 
+1
May 30, '13 at 0:30
source share

I would suggest that this is due to optimization.

Static optimization is much simpler if you can unambiguously find out what bit of memory a variable has. Pointers violate this condition, and there will be a reordering link too.

0
Apr 08 '09 at 2:05
source share

Because sometimes things cannot be overestimated. (For example, a link to Singleton.)

Because it's great in a function to know that your argument cannot be null.

But mainly because it allows you to use what is really a pointer, but which acts as a local value object. C ++ is trying hard to quote Stroustrup to make instances of the "do as ints d" class. Passing int by vaue is cheap because int is placed in a machine register. Classes are often larger than ints, and passing them at cost has significant overhead.

The ability to pass a pointer (which is often the size of an int or, possibly, two ints) that "looks", an object of value allows us to write cleaner code without "detailing the implementation" of the differences. And, along with operator overloading, it allows us to write classes using syntax similar to the syntax used with ints. In particular, this allows us to write template classes with syntax that can be equally applicable to primitive ones, such as ints and classes (for example, the Complex number class).

And, especially with operator overloading, there are places, we must return the object, but again, it is much cheaper to return the pointer. Oncve again, returning the link, our "exit".

And pointers are complicated. Not for you, maybe, not for those who implement the pointer, it's just the value of the memory address. But, remembering my CS 101 class, they defeated several students.

 char* p = s; *p = *s; *p++ = *s++; i = ++*p; 

can be confusing.

Damn, after 40 years C, people still cannot even agree if there should be a pointer declaration:

 char* p; 

or

 char *p; 
0
Apr 08 '09 at 2:21
source share

You cannot do this:

 int theInt = 0; int& refToTheInt = theInt; int otherInt = 42; refToTheInt = otherInt; 

... for the same reason why secondInt and firstInt do not have the same value here:

 int firstInt = 1; int secondInt = 2; secondInt = firstInt; firstInt = 3; assert( firstInt != secondInt ); 
0
Apr 08 '09 at 2:55
source share

I always wondered why they did not make a reference assignment operator (say: =) for this.

Just to get someone nervous, I wrote code to change the purpose of the link in the structure.

No, I do not recommend repeating my trick. It will be broken if ported to a fairly different architecture.

0
Apr 08 '09 at 3:01
source share

Be half serious: IMHO, to make them a little bigger than pointers;) You know you can write:

 MyClass & c = *new MyClass(); 

If you can write even later:

 c = *new MyClass("other") 

Would it be wise to have any links along with pointers?

 MyClass * a = new MyClass(); MyClass & b = *new MyClass(); a = new MyClass("other"); b = *new MyClass("another"); 
0
Apr 08 '09 at 11:02
source share

The fact that links in C ++ are not NULL is a side effect of their simple aliases.

0
Apr 08 '09 at 22:36
source share

I agree with the accepted answer. But for a constant, they behave like pointers.

 struct A{ int y; int& x; A():y(0),x(y){} }; int main(){ A a; const A& ar=a; ar.x++; } 

works. Cm.

Reasons for designing behavior of class reference elements passed by const reference

0
Jul 31 '12 at 13:44
source share

There's a workaround if you want a member variable to reference a link and you want to restore it. Although I find this useful and reliable, note that it uses some (very weak) assumptions about the memory layout. It is up to you to decide whether it meets your coding standards.

 #include <iostream> struct Field_a_t { int& a_; Field_a_t(int& a) : a_(a) {} Field_a_t& operator=(int& a) { // a_.~int(); // do this if you have a non-trivial destructor new(this)Field_a_t(a); } }; struct MyType : Field_a_t { char c_; MyType(int& a, char c) : Field_a_t(a) , c_(c) {} }; int main() { int i = 1; int j = 2; MyType x(i, 'x'); std::cout << x.a_; x.a_ = 3; std::cout << i; ((Field_a_t&)x) = j; std::cout << x.a_; x.a_ = 4; std::cout << j; } 

This is not very efficient, since you need a separate type for each redefined reference field and make them base classes; there is also a weak assumption that a class having one reference type will not have __vfptr or any other type_id -bound field that could potentially break the bindings during MyType execution. All compilers that I know satisfy this condition (and it would make little sense not to do this).

0
04 Oct '16 at 19:45
source share



All Articles