Let us say I have:
// This is all valid in C++11.
struct Foo {
int i = 42;
int& j = i;
};
// Let's take a pointer to the member "j".
auto b = &Foo::j; // Compiler is not happy here
// Note that if I tried to get a pointer to member "i", it would work, as expected.
Foo f;
std::cout << f.*b; // Try using the pointer to member
The compiler complains that I cannot take the address of the member because it is a reference. To be precise:
Semantic Issue: Cannot form a pointer-to-member to member 'j' of reference type 'int &'
I know doing this seems pointless, but I am only wondering why it cannot be done.
Why is this impossible?
It cannot be done because you cannot take a pointer to a reference- period.
If you could take a member pointer to a reference, this would be inconsistent with the behaviour of references on the stack. The attitude of C++ is that references do not exist. As such, you cannot form a pointer to them- ever.
For example, &f::a would have to be different to &f::b. And by de-referencing &f::b, you would effectively be achieving a pointer to a reference, which is not allowed.
C++11 standard:
§8.3.3 p3 [dcl.mptr]
A pointer to member shall not point to a static member of a class (9.4), a member with reference type, or “cv void.”
Also, in general:
§8.3.1 p4 [dcl.ptr]
[ Note: There are no pointers to references; see 8.3.2. [...] —end note ]
§8.3.2 p5 [dcl.ref]
There shall be no references to references, no arrays of references, and no pointers to references.
Member pointer (as opposed to a simple pointer to a member) is simply an offset into the structure, not a pointer at all. You can get data through it only in conjunction with the structure itself (or a pointer to a structure): the value of the offset is added to the address of the structure, and the result is dereferenced to produce the value of the member.
Now suppose a member is a reference, so accessing data through it already requires a dereference (compiler hides it from us, but it needs to spit out the corresponding instructions in its output). If C++ were to allow member pointers to references, they'd be of yet another type: an offset that needs to be added to the base, and then dereferenced twice. It is too much work to improve an already obscure feature; prohibiting it is a much better way out.
Allowing you to make a pointer to a reference does not give you any expressive power. There's nothing you can do with such a beast that you can't easily do with a reference or with a pointer. All you get out of it is added complexity.
And making a pointer to a member that is a reference is not allowed for consistency with the rule that forbids pointers to references, and because it adds even more complexity. The designers of the language probably decided that the little gains you get from these was not worth it.
This is totally just my opinion.
Related
I am confused about the meaning of "pass by reference" in C and C++.
In C, there are no references. So I guess pass by reference means passing a pointer. But then why not call it pass by pointer?
In C++, we have both pointers and references (and stuff like iterators that lies close). So what does pass by reference mean here?
In colloquial usage, "pass by reference" means that, if the callee modifies its arguments, it affects the caller, because the argument as seen by the callee refers to the value as seen by the caller.
The phrase is used independent of the actual programming language, and how it calls things (pointers, references, whatever).
In C++, call-by-reference can be done with references or pointers. In C, call-by-reference can only be achieved by passing a pointer.
"Call by value":
void foo( int x )
{
// x is a *copy* of whatever argument foo() was called with
x = 42;
}
int main()
{
int a = 0;
foo( a );
// at this point, a == 0
}
"Call by reference", C style:
void foo( int * x )
{
// x is still a *copy* of foo()'s argument, but that copy *refers* to
// the value as seen by the caller
*x = 42;
}
int main()
{
int a = 0;
foo( &a );
// at this point, a == 42
}
So, strictly speaking, there is no pass-by-reference in C. You either pass the variable by-value, or you pass a pointer to that variable by-value.
In C, there are no references
There are no reference variables. But you can refer to objects using pointers. Therefore pointers are "references" from an abstract point of view.
But then why not call it pass by pointer?
You can call it pass by pointer. Reference is a more general term than pointer. It is often preferable to use the more general term when you want to discuss abstractions and want to ignore implementation details. You would call it pass by reference for the same reason that you call a variable "integer" rather than "int32_t".
In C++, we have both pointers and references (and stuff like iterators that lies close). So what does pass by reference mean here?
Depends on context. Often it means that the function argument is a reference variable, but it may also refer to a pointer, iterator, a reference wrapper... anything that referes to an object.
Reference is an abstract concept that exists beyond c and c++; even beyond programming. In c++, the term is ambiguous with reference variables and the context and convention (which isn't universal) determines the meaning.
In C, there are no any reference variables, but you can pass by reference with using pointers.
In wikipedia, there is this definition.
In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value. So this term is for type of parameter passing as mentioned by Thomas. So yes, since C is older than C++, also this idea is older than C++.
However, in C++ both pointers and references can be used for passing to the function(Call by address and call by reference). Actually they are working the same way, they have only a few differences.
Once a reference is created, it cannot be later made to reference
another object; it cannot be reseated. This is often done with
pointers.
References cannot be NULL. Pointers are often made NULL to indicate
that they are not pointing to any valid thing.
A reference must be initialized when declared. There is no such
restriction with pointers
With these differences, if you use call by reference instead of call by pointer, you can reduce the possibility of NULL pointer error kind of problems.
Let's clear your confusion.
In C, there are no references. So I guess pass by reference means passing a pointer. But then why not call it pass by pointer?
Because every argument passing in C is pass-by-value. Even a pointer argument is a copy. But it contains (or points to, if you prefer) the same value -- memory address. That is how you can change the variable it points to, but not the pointer itself. Since it's a copy, whatever you do will not affect the pointer on the caller level.
In C++, we have both pointers and references (and stuff like iterators that lies close). So what does pass by reference mean here?
It means, that the argument is an alias of a variable on the caller level, not a copy, which allows us to change it.
Hope that helped.
A reference in general is an instance that is referencing something else. Thus in a wider sense, also a pointer can be considered as one possible implementation of a reference. References in C++ are just called references, because apart from referencing something they offer no other features.
Pass-by-reference is used in general to distinguish from pass-by-value. Whether it is via pointer or via a reference is often just a minor detail. However, with C++ references it is imho more clear what is the purpose of the function parameter. Eg:
int foo(int& a); // pass-by-reference
int foo(const int& a); // is pratically pass-by-value
// (+ avoiding the copy of the parameter)
on the other hand, with references (as compared to pointers) it is not so obvious at the call site if it is pass-by-value or pass-by-reference. E.g.
int x;
int y = foo(x); // could be pass-by-value or pass-by-reference
int z = foo(&x); // obviously pass-by-reference (as a pointer)
Imagine you have to paint your house...
by value: you bring a copy of your house to the painter => much effort (maybe on rails)
by reference: you give your house address to the painter so he can come and paint it
"Pass by reference" (or "call by reference") is a term for a type of parameter passing when calling a function, and the idea is older than C++. It does not necessarily have to be done using C++ "references". C doesn't have a built-in mechanism to do this, so you have to use pointers.
Just to add to the answers, referencing does not mean reference by address. The compiler may use any method to reference to a variable.
when you pass something by reference you're working with the address and not the value of a variable directly, If you use a reference parameter you're getting the address of the variable you pass in.
From there you can manipulate it how ever you want as the variable you passed in WILL change if you change the reference in the function. It's an easier way to work with large amounts of a data it really just saves on memory etc..
In C there are two concepts
1. Call by value - Here copy of values are passed so actual values will not change outside the function.
2. Call by reference - but here actual values (Address of actual operands) are passed so it will change the values globally.
Where in C++ there are two concepts
1. Pass by value - it is same as c, actual values will not change, scope of this values are of function only.
2. Pass by Reference - actual values (Address of actual operands) are passed so it will change the values globally, it means if values gets changed then it will affect in whole program.
In Pass by Reference, the address of operands are passed that's why it is called as Pass By Reference not as pointer.
How do you define (explain) in a formal and strict way what is reference type in C++?
I tried to google, and looked into Stroustrup's "The C++ Programming Language", but I don't see definition of this concept there.
A reference is an alias, an alternate name for an object. It is not an object itself (and in that way is not a pointer, even if some of their uses overlap with uses of pointers).
References have certain limitations to their handling, related to their non-objectness. For example, you can't create an array of references. They have to be initialized (bound, seated) as soon as they are declared, since they can't possibly exist without an object to alias.
You can however store them, and they obey the rules of automatic variables or member variables. One of their uses is to poke through C++'s pass-by-value function calls.
Note that const references have a neat side-effect of being aliases : when bound to a temporary (i.e unnamed) object, they give said object a name, and therefore extend its lifetime to that of the reference itself.
{ // Block scope
Foo fooVal = makeFoo(); // Say makeFoo() returns a (temporary, unnamed) Foo
// Here the temporary Foo is dead (fooVal is a copy).
// Foo &fooRef = makeFoo(); // Error, reference is non-const
Foo const &fooCRef = makeFoo(); // All good
// ...
// The second temporary is still alive
fooCRef.doSomethingFunny(); // Works like a charm !
} // The second temporary dies with fooRef
Beware though, it is possible (though contrived) to have an object go out of scope with references still pointing to it. You will then have dangling references, which are not to be used anymore (doing so would be Undefined Behaviour).
Foo *fooPtr = new Foo; // Here is a Foo
Foo &fooRef = *fooPtr; // Here is an alias for that Foo
delete fooPtr; // Here is the end of that Foo's life
fooRef.doSomethingFunny(); // Here comes trouble...
Regarding
” How do you define (explain) in a formal and strict way what is reference type in C++?
the C++11 standard gives the following formal and strict definition of a reference type in its
§8.3.2/1
” In a declaration T D where D has either of the forms
& attribute-specifier-seqopt D1
&& attribute-specifier-seqopt D1
and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T,” then the type of the
identifier of D is “derived-declarator-type-list reference to T.”
However, if you’re more interested in what a C++ reference practically is (apart from the colloquial use of the term), then check the definition of its meaning in an expression,
§5.5
” If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to T prior to
any further analysis. The expression designates the object or function denoted by the reference, and the
expression is an lvalue or an xvalue, depending on the expression
Effectively this means that a reference acts as an alias.
You can think of a reference as an automatically dereferenced const pointer, which explains most of the behavior except that a reference doesn't necessarily occupy storage (the compiler may be able to optimize it away completely).
According to some experts' views reference types are not C++ references per se, but in contrast to value types. I present two slightly differing definitions - of value types and of reference types.
https://abseil.io/blog/20180531-regular-types
The first is a blog post by Titus Winters, chair of the C++ subcommittee responsible for the C++ standards library.
According to Titus Winters, the difference between a value type and a reference type is the copy behaviour. When you copy an instance of a value type, you get two independent objects, which are equal first, but may differ after the modification of one of both. When you copy a reference type, you get two objects, which refer to the same data.
Reference types do not own their data. Some reference types allow modifying the referred-to data (e.g. span), some do not (e.g. string_view). Both examples given are quite useful for function parameter passing. The caller of the function assures (by convention) that the underlying data of the reference types is not destructed during the duration of the function call (as is also the case with plain C++ references).
https://learn.microsoft.com/en-us/cpp/cpp/value-types-modern-cpp?view=vs-2019
The Microsoft documentation puts reference types as synonymous to polymorphic types (types with at least one virtual function or member variable), and value types as non-polymorphic. (Non-polymorphic types are called concrete types by Bjarne Stroustrup.)
Value types are about memory and layout control, reference types are about identity.
Value types allow the compiler direct access to the members, reference types need an indirection due to runtime polymorphism.
Reference types according to Microsoft are non-copyable (to prevent slicing).
So the semantics differ, as Titus Winters defines reference types by their actual copy behaviour.
A major difference between C and C++ (other than Objects and Classes!) is references.
A reference is like a const pointer to a variable. Assigning a reference is a bit like using a pointer but with & not * and you don't need to difference. The difference is that you assign an address to a pointer but a variable to a reference variable.
The line below suggests that the value of a is copied into aref. But it is not, instead aref is a reference to the variable a. Once assigned, aref is the same as a. Any changes to aref are changes to a as example below shows
int & aref = a;
#include <stdio.h>
#include "stdafx.h"
int main()
{
int a=9;
int & aref = a;
a++;
cout << "The value of a is %i\n" << aref;
return 0;
}
Also remember that
A reference must always refer to something.NULLs are not allowed.
A reference must be initialized when it is created. An unassigned reference can not exist.
Once initialized, it cannot be changed to another variable.
If it help you please inform me, thanx
See the following:
struct A
{
std::string* get() const
{
//return const_cast<std::string*>(&m_pObj);
return &const_cast<A*>(this)->m_pObj;
}
std::string m_pObj;
};
Is dereferencing const_cast of this UB? Is there any time dereferencing the result from const_casting the constness of a pointer away doesn't invoke UB?
(I know the above example is bad practice, bad design, and could be solved with mutable - that's not the point)
Is dereferencing const_cast of this UB? Is there any time dereferencing the result from const_casting the constness of a pointer away doesn't invoke UB?
Not always, only if the object is const (the A instance is const A x;) and the dereference is used to modify the data. If it is only used to read it will not be undefined behavior, if the object is not const, (maybe not at all, maybe a const-reference to a non-const object) it won't be UB either.
No, it is only UB if the referenced object has been declared as const originally and you subsequently modify the data obtained by the cast (§5.2.11/7 and §7.1.6.1/4). The following is legal:
A a;
a.get()->clear();
while this isn’t (and is consequently UB):
A const a;
a.get()->clear();
No. To wit:
5.2.2 Function call
5 [ Note: a function can change the values of its non-const parameters, but these changes cannot affect the
values of the arguments except where a parameter is of a reference type (8.3.2); if the reference is to a
const-qualified type, const_cast is required to be used to cast away the constness in order to modify
the argument’s value. Where a parameter is of const reference type a temporary object is introduced if
needed (7.1.6, 2.14, 2.14.5, 8.3.4, 12.2). In addition, it is possible to modify the values of nonconstant objects
through pointer parameters. —end note ]
However,
5.2.11 Const cast
12 [ Note: some conversions which involve only changes in cv-qualification cannot be done using const_cast.
For instance, conversions between pointers to functions are not covered because such conversions lead to
values whose use causes undefined behavior. For the same reasons, conversions between pointers to member
functions, and in particular, the conversion from a pointer to a const member function to a pointer to a
non-const member function, are not covered. —end note ]
A compiler is free to store a const value in read-only memory, it is free to make assumptions that it will never change when optimising the program. If you cast away the constness, you are breaking the contract with the compiler so technically anything can happen.
Realistically, it is pretty rare for a compiler to do something that will be broken by const_cast-ing, but in theory it is possible.
I'm new to the C++ community, and just have a quick question about how C++ passes variables by reference to functions.
When you want to pass a variable by reference in C++, you add an & to whatever argument you want to pass by reference. How come when you assign a value to a variable that is being passed by reference why do you say variable = value; instead of saying *variable = value?
void add_five_to_variable(int &value) {
// If passing by reference uses pointers,
// then why wouldn't you say *value += 5?
// Or does C++ do some behind the scene stuff here?
value += 5;
}
int main() {
int i = 1;
add_five_to_variable(i);
cout << i << endl; // i = 6
return 0;
}
If C++ is using pointers to do this with behind the scenes magic, why aren't dereferences needed like with pointers? Any insight would be much appreciated.
When you write,
int *p = ...;
*p = 3;
That is syntax for assigning 3 to the object referred to by the pointer p. When you write,
int &r = ...;
r = 3;
That is syntax for assigning 3 to the object referred to by the reference r. The syntax and the implementation are different. References are implemented using pointers (except when they're optimized out), but the syntax is different.
So you could say that the dereferencing happens automatically, when needed.
C++ uses pointers behind the scenes but hides all that complication from you. Passing by reference also enables you to avoid all the problems asssoicated with invalid pointers.
When you pass an object to a function by reference, you manipulate the object directly in the function, without referring to its address like with pointers. Thus, when manipulating this variable, you don't want to dereference it with the *variable syntax. This is good practice to pass objects by reference because:
A reference can't be redefined to point to another object
It can't be null. you have to pass a valid object of that type to the function
How the compiler achieves the "pass by reference" is not really relevant in your case.
The article in Wikipedia is a good ressource.
There are two questions in one, it seems:
one question is about syntax: the difference between pointer and reference
the other is about mechanics and implementation: the in-memory representation of a reference
Let's address the two separately.
Syntax of references and pointers
A pointer is, conceptually, a "sign" (as road sign) toward an object. It allows 2 kind of actions:
actions on the pointee (or object pointed to)
actions on the pointer itself
The operator* and operator-> allow you to access the pointee, to differenciate it from your accesses to the pointer itself.
A reference is not a "sign", it's an alias. For the duration of its life, come hell or high water, it will point to the same object, nothing you can do about it. Therefore, since you cannot access the reference itself, there is no point it bothering you with weird syntax * or ->. Ironically, not using weird syntax is called syntactic sugar.
Mechanics of a reference
The C++ Standard is silent on the implementation of references, it merely hints that if the compiler can it is allowed to remove them. For example, in the following case:
int main() {
int a = 0;
int& b = a;
b = 1;
return b;
}
A good compiler will realize that b is just a proxy for a, no room for doubts, and thus simply directly access a and optimize b out.
As you guessed, a likely representation of a reference is (under the hood) a pointer, but do not let it bother you, it does not affect the syntax or semantics. It does mean however that a number of woes of pointers (like access to objects that have been deleted for example) also affect references.
The explicit dereference is not required by design - that's for convenience. When you use . on a reference the compiler emits code necessary to access the real object - this will often include dereferencing a pointer, but that's done without requiring an explicit dereference in your code.
What would be better practice when giving a function the original variable to work with:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
or:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW: Is there any reason to pick one over another?
My rule of thumb is:
Use pointers if you want to do pointer arithmetic with them (e.g. incrementing the pointer address to step through an array) or if you ever have to pass a NULL-pointer.
Use references otherwise.
I really think you will benefit from establishing the following function calling coding guidelines:
As in all other places, always be const-correct.
Note: This means, among other things, that only out-values (see item 3) and values passed by value (see item 4) can lack the const specifier.
Only pass a value by pointer if the value 0/NULL is a valid input in the current context.
Rationale 1: As a caller, you see that whatever you pass in must be in a usable state.
Rationale 2: As called, you know that whatever comes in is in a usable state. Hence, no NULL-check or error handling needs to be done for that value.
Rationale 3: Rationales 1 and 2 will be compiler enforced. Always catch errors at compile time if you can.
If a function argument is an out-value, then pass it by reference.
Rationale: We don't want to break item 2...
Choose "pass by value" over "pass by const reference" only if the value is a POD (Plain old Datastructure) or small enough (memory-wise) or in other ways cheap enough (time-wise) to copy.
Rationale: Avoid unnecessary copies.
Note: small enough and cheap enough are not absolute measurables.
This ultimately ends up being subjective. The discussion thus far is useful, but I don't think there is a correct or decisive answer to this. A lot will depend on style guidelines and your needs at the time.
While there are some different capabilities (whether or not something can be NULL) with a pointer, the largest practical difference for an output parameter is purely syntax. Google's C++ Style Guide (https://google.github.io/styleguide/cppguide.html#Reference_Arguments), for example, mandates only pointers for output parameters, and allows only references that are const. The reasoning is one of readability: something with value syntax should not have pointer semantic meaning. I'm not suggesting that this is necessarily right or wrong, but I think the point here is that it's a matter of style, not of correctness.
Pointers
A pointer is a variable that holds a memory address.
A pointer declaration consists of a base type, an *, and the variable name.
A pointer can point to any number of variables in lifetime
A pointer that does not currently point to a valid memory location is given the value null (Which is zero)
BaseType* ptrBaseType;
BaseType objBaseType;
ptrBaseType = &objBaseType;
The & is a unary operator that returns the memory address of its operand.
Dereferencing operator (*) is used to access the value stored in the variable which pointer points to.
int nVar = 7;
int* ptrVar = &nVar;
int nVar2 = *ptrVar;
Reference
A reference (&) is like an alias to an existing variable.
A reference (&) is like a constant pointer that is automatically dereferenced.
It is usually used for function argument lists and function return values.
A reference must be initialized when it is created.
Once a reference is initialized to an object, it cannot be changed to refer to another object.
You cannot have NULL references.
A const reference can refer to a const int. It is done with a temporary variable with value of the const
int i = 3; //integer declaration
int * pi = &i; //pi points to the integer i
int& ri = i; //ri is refers to integer i – creation of reference and initialization
You should pass a pointer if you are going to modify the value of the variable.
Even though technically passing a reference or a pointer are the same, passing a pointer in your use case is more readable as it "advertises" the fact that the value will be changed by the function.
If you have a parameter where you may need to indicate the absence of a value, it's common practice to make the parameter a pointer value and pass in NULL.
A better solution in most cases (from a safety perspective) is to use boost::optional. This allows you to pass in optional values by reference and also as a return value.
// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
if (optional_str)
{
cout << *optional_str << std::endl;
}
else
{
cout << "(no string)" << std::endl;
}
}
// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
if (return_nothing)
{
return boost::optional<int>();
}
return boost::optional<int>(42);
}
Use a reference when you can, use a pointer when you have to.
From C++ FAQ: "When should I use references, and when should I use pointers?"
A reference is an implicit pointer. Basically you can change the value the reference points to but you can't change the reference to point to something else. So my 2 cents is that if you only want to change the value of a parameter pass it as a reference but if you need to change the parameter to point to a different object pass it using a pointer.
Consider C#'s out keyword. The compiler requires the caller of a method to apply the out keyword to any out args, even though it knows already if they are. This is intended to enhance readability. Although with modern IDEs I'm inclined to think that this is a job for syntax (or semantic) highlighting.
Pass by const reference unless there is a reason you wish to change/keep the contents you are passing in.
This will be the most efficient method in most cases.
Make sure you use const on each parameter you do not wish to change, as this not only protects you from doing something stupid in the function, it gives a good indication to other users what the function does to the passed in values. This includes making a pointer const when you only want to change whats pointed to...
Pointers:
Can be assigned nullptr (or NULL).
At the call site, you must use & if your type is not a pointer itself,
making explicitly you are modifying your object.
Pointers can be rebound.
References:
Cannot be null.
Once bound, cannot change.
Callers don't need to explicitly use &. This is considered sometimes
bad because you must go to the implementation of the function to see if
your parameter is modified.
A reference is similar to a pointer, except that you don’t need to use a prefix ∗ to access the value referred to by the reference. Also, a reference cannot be made to refer to a different object after its initialization.
References are particularly useful for specifying function arguments.
for more information see "A Tour of C++" by "Bjarne Stroustrup" (2014) Pages 11-12