I have a method:
odp(foo& bar);
I'm trying to call it:
foo baz;
odp(&baz);
I get a compiler error:
error C2664: "odp" cannot convert parameter 1 from 'foo *' to 'foo &'
What am I doing wrong? Aren't I passing in a reference to baz?
UPDATE: Perhaps I have a misconception about the relationship between pointers and references. I thought that they were the same, except references couldn't be null. Is that incorrect?
When you apply the unary & operator to an object, you get a pointer to that object, not a reference. You need a reference in this case. In order to initialize a reference parameter, you don't need to apply any operators at all: an lvalue object can immediately be used by itself to initialize a reference of the appropriate type.
The informal synonymity between the notions of "pointer" and "reference" (as in "pass by pointer" and "pass by reference") is specific to C language. But in C++ they mean two completely different things.
The odp function need a reference to a foo var whereas you are passing the adress of a foo var (pointer).
Just pass baz like:
foo baz;
opd(baz);
And it will compile.
No, you're passing a pointer to baz. Drop the &.
When you use &baz, you are actually saying address of baz, so you are passing a pointer.
References and pointers are NOT the same in C++ - although you have probably read that most compilers implement references using pointers at the machine-code level. You don't need to care how they are implemented by the compiler - but what the semantics of a "reference" and a "pointer" are in C++.
int i = 5;
int &j = i; // j refers to the variable i
// wherever the code uses j, it actually uses i
j++; // I just changed i from 5 to 6
int *pj = &i; // pj is a pointer to i
(*pj)--; // I just changed i back to 5
Note that I can change pj to point to another integer, but I cannot change the reference j to refer to another integer.
int k = 10;
pj = &k; // pj now actually points to k
(*pj)++; // I just changed k to 11
j = k; // no, this doesn't change the reference j to refer to k instead of i,
// but this statement just assigned k to i, that is, i now equals 11!
In C++, references are aliases, not addresses. You can, for instance, have multiple names for a single pointer, just as you might have multiple names for a single real object.
When you declare a function taking a reference parameter, the function will automatically alias whatever variable you pass to it. Whatever it aliases, though, must be of the same type as the reference. In your case, you are aliasing an int* with an int reference, which doesn't make sense.
Maybe you're being misled by old C conventions? In C, you "pass by reference" by creating a pointer, because the language doesn't have references - you use the pointer to "reference" the original variable. In C++, references are supported by the language and there's no need to create a pointer to the variable when you call the function.
foo baz;
odp(baz);
Related
I am working with an API wherein the caller passes in an array of pointers to stuff, as well as the length of the array. To make my code more readable/maintainable, I would like to be able to effectively give names to each argument rather than refer to them as arg[0], arg[1], etc. Is it safe to declare references to all of the possible arguments even if the length of the passed-in array can be different sizes due to optional arguments?
I am trying to do something like this:
void myFunc(int out_args[], size_t nargs) {
int &foo = out_args[0];
int &bar = out_args[1]; // bar is optional argument. is this safe?
...
foo = 5;
if(2 >= nargs)
bar = 10;
...
}
Note that the arguments are output arguments, so I really want to have references to them. So, is it safe to have a dangling-ish reference to args[1] if I never actually use it?
My guess is that this is safe because I imagine the way references are implemented is to treat & in the variable declaration of references as * const, and whenever I use the references, then the compiler automatically dereferences the pointers for me. Ie, under the hood, I imagine that what I wrote is translated to something like
void myFunc(int out_args[], size_t nargs) {
int *const foo = &out_args[0];
int *const bar = &out_args[1]; // bar is optional argument. is this safe?
...
*foo = 5;
if(2 >= nargs)
*bar = 10;
...
}
In this case, I believe the code never actually accesses memory it shouldn't, so if the version above is equivalent to this, then I should be ok, right?
EDIT:
I'm basically writing a plug in, and the API I'm using and can't do anything about can call my code with either something like
int ret_vals[1]; // only care about 1 return value
myFunc(ret_vals, 1);
or
int ret_vals[2]; // care about both return values
myFunc(ret_vals, 2);
or even
myFunc(NULL, 0); // ignore all return values; just marvel at the side effects
and my code needs to work in all cases.
It is undefined behaviour to evaluate the expression args[1] if args isn't a pointer to the first element of an array of at least two elements. Taking the address immediately, like &args[1], is valid only if args points to the first element of an array of at least one element.
Basically, don't do it.
So, is it safe to have a dangling-ish reference to args[1] if I never actually use it?
The standard impose that a reference shall be bound to a valid object in § 8.3.2:
There shall be no references to references, no arrays of references,
and no pointers to references. [...] A reference shall be initialized
to refer to a valid object or function. [ Note: in particular, a null
reference cannot exist in a well-defined program, because the only way
to create such a reference would be to bind it to the “object”
obtained by dereferencing a null pointer, which causes undefined
behavior. [...] — end note ]
It means that it is not safe.
My guess is that this is safe because I imagine the way references are
implemented is to treat & in the variable declaration of references as
* const, and whenever I use the references, then the compiler automatically dereferences the pointers for me.
No, don't do that. Again, the standard doesn't specify how references shall be implemented. In fact in § 8.3.2 it states that:
It is unspecified whether or not a reference requires storage.
As for your code: you could name the parameters once you are sure they exists.
void myFunc(int out_args[], size_t nargs) {
int &foo = out_args[0];
...
foo = 5;
if(nargs >= 2) {
int &bar = out_args[1];
bar = 10;
}
...
}
I feel obligated to make you notice that the use of C-style arrays in C++ is discouraged. It is generally a good idea to use std::vector or std::array instead.
Take the following example. I create a function pointer named s, set it to f and call it. This compiles fine of course:
void f() {}
int main() {
void (*s)();
s = f;
s();
}
But take this next example, where I declare s now as a "function reference" (if it's so called) and set to f inline. This compiles fine as well:
void f() {}
int main() {
void (&s)() = f;
s();
}
What are the differences between these two ways to create and initialize a function-pointer? Note that when I use the reference syntax I am required to initialize it "in-line" to f whereas with the "pointer" syntax I had the ability to do it both ways. Can you explain that as well? And with that, can you explain what their differences are in terms of usability, and when must I use one form over the other?
Fundamentally the calling side has no distinct difference. But the decl side definitely does. As you have pointed out, references must be initialized to reference something. This makes them "safer", but even then there is no guarantee of "safety".
The function pointer need NOT point to a function at all. It could be NULL, or even uninitialized (pointing to garbage). Not that it matters, because you can always change it later (something you can NOT do with references).
void (*s)(); // uninitialized
or
void (*s)() = NULL; // set to null
and later
void foo()
{
}
s = foo;
You can do none of those with a reference. The reference must be initialized to something and preferabley something valid:
void (&f)() = foo; // ok. also references foo().
void (&f)() = *s; // also ok, but wait, is s valid?? does it have to be??
However, even here a function reference is not guaranteed to be safe, just safer. You can certainly do this:
void (*s)();
void (&f)() = *s;
You may get a compiler warning out of this (I do, "s used before being initialized") but in the end f still is now a reference to a "function" that isn't a function at all; just the random stack garbage in the s pointer. Worse, since references cannot be reassigned. this thing will always point at garbage.
The differences are the same as for any pointer/reference.
References must be initialized and cannot be reassigned later:
int i,j;
int &r = i;
r = j; // i = j, not &r == &j
References cannot be treated as objects distinct from the object they reference (as opposed to pointers, which are objects distinct from the object they point at)...
int i;
int *p = &i; // &p != &i
int &r = i; // &r == &i
Using a function pointer looks syntactically the same as using a reference, but that's because of a special rule with function pointers that allows you to use them without dereferencing them.
You said it yourself, a difference is that with a reference, you have to bind it upon declaration, which guarantees that references always refer to valid objects.
Another difference is that references cannot be rebinded after they are declared, so they refer to one and only one object throughout their lives.
Other than that they are the same thing.
I have met some purists that prefer references and said that pointers are a vestige of C that shouldn't be used.
Other people prefer pointers because they are more "explicit" about the fact that they are pointers.
Whether using one or the other depends on your needs. The way to choose is, use a reference if possible, but if you really need to be able to point it to a different function, then use a pointer.
A reference to a type P is a lot like a const pointer to a type P (not a pointer to a const P, which is different).
As it happens most of the ways they differ are not important if your type P is a function type. & behaves slightly differently, you can directly assign the pointer to a non const pointer, and functions that take one may not take the other.
If the type P was not a function type there would be loads of other differences -- operator=, lifetime of temporaries, etc.
In short, the answer is 'not much'.
Function identifiers are expressions of function type, but they implicitly convert to pointer-to-function type or reference-to-function type. So they can be passed to constructor of either reference or pointer and to operator= of pointer.
Since references syntactically behave like instances, there is no way to act on the reference rather than the referred object. That's why they can only be initialized. By the way prefered syntax in C++ is with parenthesis, not =.
You should use reference when possible and pointers only if you can't use reference. The reason is that since many things can't be done to reference (pointing to NULL, changing referred object, deleting it etc.) there is fewer things you have to look for when reading the code. Plus it saves some * and & characters.
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.
It is not possible to assign an integer value to a reference variable directly, say like:
int &x=10; //not possible
Is there any other way we can modify this statement to make it possible?
But not like this:
int a=10;int &x=a;
This works fine. But I want some other way or modify a little bit my expression and make it work!
The reference as the name says has to reference to something. How do you want to assign a value to it if it doesn't reference anything?
The reason it doesn't work is because 10 is of the type "const int". You can turn that into a reference, but you can't make it non-const without violating some logic at the least.
const int &a = 10;
that'll work.
int &b = const_cast<int &>(static_cast<const int &>(10));
will also compile, but you can't modify b (as that would imply modifying the actual "10" value).
The crux is that 10 is a constant – somewhat obviously: you cannot change its value. But if you try to assign it to an int reference, this would mean that the value were modifiable: an int& is a modifiable value.
To make your statement work, you can use a const reference:
int const& x = 10;
But as “cnicutar” has mentioned in a comment, this is pretty useless; just assign the 10 to a plain int.
You can't bind a reference-to-nonconst to anything immutable.
The standard permits storing compile time constants in ROM (btw, attempting to modify const_cast<>ed compile time constants yields undefined behaviour)
This would basically strip of the const, even if the const is invisible, therefore subverting the whole const-correctness-thing
However, you can bind a reference-to-const to nearly everything, including temporaries:
GotW: A candidate for the most important const
Consider this a "feature".
References refer to objects (perhaps temporary objects), not to values. If you want to store a value somewhere, assign it to an object, not to a reference.
As a special case, const int &a = 10; initializes the reference a to refer to a temporary object with the value 10, and it extends the lifetime of that temporary to the end of the scope of a (12.2/5). That's pretty useless with an integer literal, but occasionally useful with objects of class type. Still, this does not assign an integer value to a reference. It creates a temporary, and binds a reference to the temporary.
in the C++0x, you can use int&& (rvalue references ), but this can be used as function parameter.
I want to know the meaning of & in the example below:
class1 &class1::instance(){
///something to do
}
The & operator has three meanings in C++.
"Bitwise AND", e.g. 2 & 1 == 3
"Address-of", e.g.: int x = 3; int* ptr = &x;
Reference type modifier, e.g. int x = 3; int& ref = x;
Here you have a reference type modifier. Your function class1 &class1::instance() is a member function of type class1 called instance, that returns a reference-to-class1. You can see this more clearly if you write class1& class1::instance() (which is equivalent to your compiler).
This means your method returns a reference to a method1 object. A reference is just like a pointer in that it refers to the object rather than being a copy of it, but the difference with a pointer is that references:
can never be undefined / NULL
you can't do pointer arithmetic with them
So they are a sort of light, safer version of pointers.
Its a reference (not using pointer arithmetic to achieve it) to an object.
It returns a reference to an object of the type on which it was defined.
In the context of the statement it looks like it would be returning a reference to the class in which is was defined. I suspect in the "Do Stuff" section is a
return *this;
It means that the variable it is not the variable itself, but a reference to it. Therefore in case of its value change, you will see it straight away if you use a print statement to see it. Have a look on references and pointers to get a more detailed answer, but basecally it means a reference to the variable or object...