5

I am learning about references in C++. In particular, i have learnt that references are not actual objects. Instead they refer to some other object. That is, reference are just alias for other objects.

Then i came across this which says:

Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. It is neither a pointer to the object, nor a copy of the object. It is the object. There is no C++ syntax that lets you operate on the reference itself separate from the object to which it refers.

I get that the above quote means that we can't operate on the reference itself separate from the object to which it refers but it still seems to imply that "a reference is an object".

Also, i have come across the the sentence given below:

In ISO C++, a reference is not an object. As such, it needs not have any memory representation.

I don't have a link to this 2nd quote but i read it in one of SO's post somewhere.

My question is that assuming the second quote is also from the standard(which may not be the case), doesn't these 2 quoted statements contradict each other. Or at least the first quote is misleading. Which one is correct.

My current understanding(by reading books like C++ Primer 5th edition) is that references are an alias for objects. Which leads me to the thinking that they should not take any space in memory.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • 6
    When the first quote says **It is the object**, it is saying not that the reference is an object, but that the reference is the **referred object**. – user4581301 Mar 18 '22 at 16:01
  • Correct me if I'm wrong, but references may or may not take space in memory. It's compiler-based. Ref: https://stackoverflow.com/questions/39481687/c-do-references-occupy-memory – The Coding Fox Mar 18 '22 at 16:02
  • The standard quote is a note. Notes are informal and sometimes contradict with rules when interpreted too strictly. In such case, the rules are correct and the note is not. If you want less contradictory wording, read it as "reference names the object". – eerorika Mar 18 '22 at 16:05
  • In the abstract concept of the C++ virtual machine, a reference is just an alias to the object it refers to. It doesn't need to exist at all, just like `using int_vec = std::vector`; creates an alias, it doesn't create a new type. In the technical sense a pointer might be needed so the compiler can pass around a handle to the object the reference refers to, but that is just an implementation detail. – NathanOliver Mar 18 '22 at 16:08
  • What a reference "is" is a purely philosophical question; it's an abstract concept that people can think about in different ways. But I'm not sure of the practical importance. Is there a particular piece of code whose observable behavior you think would hinge on this? – Nate Eldredge Mar 18 '22 at 16:10
  • What this passage is trying to say is that the reference is an alias - another name - for the object it refers to. The object behaves exactly the same regardless of which name you use to access or manipulate it, whether the name of the variable in the original definition, or a reference bound to the object later. Once a reference is declared and bound to an object, anything you do with that reference is in fact an operation on the referred-to object. – Igor Tandetnik Mar 18 '22 at 16:11
  • I think the name itself doesn't take space either, it's the referred to object (or the storage, when no active object) which take the space. (and unnamed temporary also take space) (not language-lawyer) – apple apple Mar 18 '22 at 16:11
  • @NateEldredge I was thinking of confirming that whether or not references take any space and was aware that compilers implement it using pointers. Then i thought that since pointers take space then reference should also take space. Which was contradicting with my current thinking that reference are just alias and should not take any space. So i started searching on the web about reference and came across the first quote mentioned in my question. – Jason Mar 18 '22 at 16:12
  • Whether or not anything "takes space" is an implementation detail and so is outside the scope of the standard. As one point, however, you can't take the address of a reference; you just get back the address of the referred object. So the implementation is not *required* to allocate a specific chunk of memory for a reference, nor to act as if it does so. – Nate Eldredge Mar 18 '22 at 16:15
  • @SolvedGames A variable is always an object, anything with a name is an object. But you can also return a reference from a function and the return value is not an object but an rvalue. You have to assign it to some variable for it to become an object. But sometimes such rvalues can become objects implicitly, e.g. when they are converted to another type in a function call: `foo(bar())` where foo takes a reference and bar returns a reference of another type that is implicitly converted. Watch this talk https://www.youtube.com/watch?v=XS2JddPq7GQ – Goswin von Brederlow Mar 19 '22 at 02:23
  • @GoswinvonBrederlow Oh I'll keep that in mind. Thanks forinforming me that. – The Coding Fox Mar 19 '22 at 03:10

4 Answers4

3

Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. ...

Notes are informal and usually should not to be interpreted as strict rules. If an interpretation contradicts with standard rules, then that interpretation is wrong.

References and objects are different kinds of entities. A reference is not an object distinct from the one that it names. It isn't possible to form a pointer to a reference. A "pointer to reference" isn't even a valid type category.

The note is trying to say that reference "is" the object which it names in the sense that using the reference is using the referred object.

I was thinking of confirming that whether or not references take any space

References take space or they don't take space. It's up to the language implementation to figure out whether it needs space in each case.

Standard quote:

[dcl.ref] It is unspecified whether or not a reference requires storage


Outside of standard specifications, if you want an example of reference using space, try adding a reference member to a class and you are very likely to observe that the size of the class increases.

since pointers take space then reference should also take space. ...

Pointers do take space in the abstract machine that the standard specifies. But if you never observe the storage, then it's entirely possible that the storage never exists in practice. A significant difference between references and pointers is that you cannot observe the storage of a reference directly.

Philosopher: "If a tree falls in an abstract machine and no one is around to observe it, does it have an effect?"

Optimiser: "Not if I can help it."

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Ok so is it correct to say that according to the standard, a reference is an alias for another object. But the standard does not "require" that references must not take any space. Implementations are free to implement reference as they see fit as long as it matches the behavior of reference as described by the standard? – Jason Mar 18 '22 at 16:22
  • @Anya Yes, exactly. – eerorika Mar 18 '22 at 16:24
  • Yes. Consider by contrast actual first-class objects which have specified minimum sizes and must be addressable – Useless Mar 18 '22 at 16:25
2

The first quote is really saying the reference is not separable from the object.

... still seems to imply that "a reference is an object".

It really implies that a reference is a non-separable, non-first-class alias for an object, exactly as you first said.

The difficulty with these discussions is that the standardese meaning of "object" is already different from the meaning used in most less-formal contexts.

Let's start simple:

int a;

Would often be described as declaring an integer object a, right? It actually

  1. declares an integer object
  2. binds the name a to that object in the appropriate scope

Now, if we write

int &b = a;

we could say that b is the object in the same way as we could say that a is the object. Actually neither are correct, but given that informal text already uses the latter, it's no worse.

We should instead say that the name b refers to the same object as the name a. This is exactly consistent with calling it an alias, but informal or introductory texts would seem pretty cumbersome if they wrote "... the integer object referred to by the name a ..." everywhere instead of just "the integer a".

As for taking space in memory ... it depends. If I introduce 100 aliases for a single object inside a single function I'd be really surprised if the compiler didn't just collapse them (although of course they might still show up in debug symbols). No information is being lost here by eliding the redundant names.

If I pass an argument by reference to a non-inlined function, some actual information is being communicated, and that information must be stored somewhere.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
Useless
  • 64,155
  • 6
  • 88
  • 132
  • Your first example does make sense. In particular, i like the second point/detail where you wrote: *"binds the name `a` to that object in the appropriate scope"*. Just one question: Is it(the second point) what must happen according to the C++ standard or another implementation detail? – Jason Mar 18 '22 at 16:17
  • References are not required to take space, except in the case where they couldn't function correctly without taking space: that's why I mentioned passing a function parameter by reference. The standard still doesn't require storage space there, but the implementation of a calling convention probably does. – Useless Mar 18 '22 at 16:23
  • _It actually declares an integer object; binds the name `a` to that object in the appropriate scope_ Do you mean «variable» instead of «object»? – Language Lawyer Mar 18 '22 at 16:51
  • No. The declaration _does_ introduce a variable, because it's a reference to an object, but I'm discussing the distinction between the object itself and the reference. Those are the categories (mis)used in the original quotes, and I don't think adding a 3rd overlapping category is likely to clarify anything. – Useless Mar 18 '22 at 16:58
  • 1
    I just don't think we say "bind a name to object", but rather "to variable". – Language Lawyer Mar 18 '22 at 17:13
  • @LanguageLawyer Object and variable are same in this context(or in any context?) right? So that shouldn't make a difference. I may be wrong. Please correct me by pointing to an article/source that explains the difference. – Jason Mar 18 '22 at 17:14
  • @Anya _Object and variable are same in this context(or in any context?) right?_ No. – Language Lawyer Mar 18 '22 at 17:15
  • I second @LanguageLawyer here. – Bathsheba Mar 18 '22 at 17:39
  • 1
    @LanguageLawyer I have asked a separate question [here](https://stackoverflow.com/questions/71531033/difference-between-an-object-and-a-variable-in-c) regarding this. [cppref](https://en.cppreference.com/w/cpp/language/object) says: *"A variable is an object or a reference that is not a non-static data member, that is introduced by a declaration. "*. So a variable and object seems to be the same(except for a non-static data member ofcourse). – Jason Mar 18 '22 at 17:46
  • @Anya _I have asked a separate question ... a variable and object seems to be the same_ AFAIR it has already been asked a couple of times – Language Lawyer Mar 18 '22 at 17:54
2

A reference provides another way of referring to an object. That's useful particularly when passing parameters by reference to functions. More formally, a reference is an alias that binds to a variable including, in this case, an anonymous temporary.

Fortunately we don't need to concern ourselves how they are implemented. That's the job of the compiler, and techniques vary. The C++ standard does not require them to occupy any memory.

There is a way of distinguishing reference types by the way. Non-separability is really more about not being able to bind the reference to any other variable. See

#include <iostream>
#include <type_traits>

int main() {
    int a = 0;
    int& ref = a;
    std::cout << (
        std::is_reference<decltype(ref)>::value ? "pay me a bonus\n" : "reformat my hard disk\n"
    );
    std::cout << (
        std::is_reference<decltype(a)>::value ? "pay me a bonus\n" : "reformat my hard disk\n"
    );
}

Note finally that &a and &ref must always be the same.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
0

What a reference actually "is" doesn't make much sense: you could say it is the referenced object or that it is an alias to it, and these claims are both true in some sense.

int main()
{
    int a(0);
    int& ref(a);

    ref = 1; // Will actually affect the value of a

    return 0;
}

Let's go through this program line by line.

  • int a(0); allocates some memory (usually 4 bytes) on the stack to hold an integer.
  • int& ref(a); doesn't necessarily allocate memory, and wether it actually will is compiler-specific. In this sense, ref itself is not an object: it is simply an alias, another name, for a. This is what the second quote means by "a reference is not an object". (Please note that sometimes, when the what object is referenced can't be known at compile-time for example, a reference has to reserve additional space for the object's address. In these cases, references are just syntactic sugar for pointers.)
  • ref = 1; sets the value of a to one. In this sense, you can think of ref as being precisely the same object as a. Any operation "on" the reference will actually operate on the referenced object. This is what the first quote means by "It is the object".
Debaug
  • 452
  • 4
  • 14
  • Since this is an anally-retentive language-lawyer type question, you should swap out usage of the colloquial term "stack" for "automatic storage" to maintain correctness. Similarly *In these cases, references are just syntactic sugar for pointers.* would be better worded as *In these cases, references are often just syntactic sugar for pointers.* or *In these cases, references are typically implemented with pointers.* because as far as the Standard's concerned the implementation could use Eldar majick or quantum entanglement to get the job done. – user4581301 Mar 18 '22 at 18:02