Pointer address as reference in function - c++

I've got one general question, why can't I pass the the pointer's address as a reference?
void domdom(string &foo)
{
foo = "";
}
string fooso = "blabal";
string* p_fooso = fooso;
domdom(p_fooso); // <-- why is that not possible? And what should I pass to be able to modify foosoo?
I know I could change the function domdom to accept (string* foo), but is it also possible to modify the string fooso in the function by using the pointer to it and the given function?

why can't i pass the the pointer's address as a reference?
Because that's how the language is defined.
Instead, you can dereference the pointer to get a reference to the string:
domdom(*p_fooso);
or, pass the actual object directly:
domdom(fooso);
Also note that string* p_fooso = fooso; doesn't compile. You have to write string* p_fooso = &fooso;.

Just declare p_fooso as a string reference type.
You might want to rename variable as r_fooso!
string& r_fooso=fooso;

Pointers and references are similar under the hood, but are used differently, which is why mixing them by implicit conversion is not allowed by C++, to avoid confusion.
However you can always explicitly convert a reference to a pointer, and vice versa, without incurring the overhead of a copy. For example, if you call the function as domdom(*p_fooso), you will get the desired effect, i.e. the function will receive reference to the exact object you'd get by dereferencing the pointer.

Related

Unique_ptr out of scope

I'm having an issue passing unique_ptrs to functions, it seems they go out of scope when I pass to askQuestion.
hears my code.
char askQuestion(string *questions[8], unique_ptr<binaryBase>answered) {
bool asked = false;
char input = '0';
while (!asked) { // loop until you find a question that has not been asked
int randomQuestion = (rand() % 8); // generate a random number
if (!(answered->getBit(randomQuestion))) { // check if the question has been answered
getInput(input, *questions[randomQuestion]);
answered->toggleBit(randomQuestion);
asked = true;
}
}
return input;
}
these two functions access unique_ptrs, function below relies on function above for input.
when I call askQuestion I get "(variable) cannot be referenced -- it is a deleted function"
bool checkAnswer(char answer, int place, binaryBase* reference) {
/* if the answer is T and the correct answer is true, returns true
if the answer is F and the correct answer is false, returns true
return false otherwise
*/ return((answer=='T'&&reference->getBit(place))||(answer=='F'&&!reference->getBit(place)));
}
binaryBase is a simple custom class and only has a 8 int as data and getters and setters for bits, this treats the 8 bit int as a byte to store "boolean" answers for the program.
I'm not seeing a call to askQuestion() in your example. However, I can see that askQuestion() is an "observer" of the answered parameter. A unique_ptr is used to transfer ownership of a pointer, not for just observing it. So you should define that function as:
char askQuestion(string *questions[8], binaryBase& answered)
instead. Use a reference here instead of a pointer to make it clear that passing null is not allowed. (Of course change all occurrences of answered-> to answered.)
When you call that function and want to pass an object managed by a unique_ptr<binaryBase> ptr, then pass the managed object, not the unique_ptr itself with *ptr.
In cases where you actually do want to transfer ownership of the pointer, then you need to move the pointer:
void func(std::unique_ptr<binaryBase>);
// ...
std::unique_ptr<binaryBase> ptr = /* ... */
func(std::move(ptr));
After the call to func(), ptr does not contain an object anymore. func() took ownership of it.
unique_ptr is a "move-only type". It cannot be copied because its copy constructor and copy assignment operator have been deleted, which is the reason of your original compilation error.
char askQuestion(string *questions[8], unique_ptr<binaryBase>answered)
You are attempting to pass a std::unique_ptr by value to askQuestion() but it's a move-only type. It represents a dynamically allocated object that is not shared by more than one object at a time. You can only move a unique_ptr or pass it by reference. If you intend to pass ownership of the unique pointer then you have to use std::move:
askQuestion(questions, std::move(answered));
where answered is a std::unique_ptr<binaryBase>. Once ownership has transferred to a function then the caller cannot use that unique pointer again.
If you do not want to pass ownership then it can be passed by reference. Change askQuestion() to do that:
char askQuestion(string *questions[8], unique_ptr<binaryBase> &answered); //non-const lvalue reference
or
char askQuestion(string *questions[8], const unique_ptr<binaryBase> &answered); //const lvalue reference
When passing by reference the function can use the pointer but not own it, unless you explicitly use std::move within the function with a non-const lvalue reference unique pointer (a const lvalue reference can't be moved).
bool checkAnswer(char answer, int place, binaryBase* reference)
In your code you are passing a pointer to binaryBase to the function checkAnswer(). Again there's no need for this function to own the unique pointer, so you can pass the unique pointer by reference as shown above or use std::unique_ptr's get() method to get a pointer to the object.
You might like to check out this answer, which deals with different ways of passing a unique pointer comprehensively.

How to pass the unique pointer to specific param required in function?

A short yet effective example below:
std::unique_ptr<float> x(new float[whatever_size]);
I have a function with prototype:
void function(float*&);
How can I go about calling it by passing in the x.
I tried:
function(x.get()); // complains no argument matches float*&
function(&x.get()); // complains requires lvalue.
A short answer with an explanation would be great.
Thanks!
To start with, you should know that a unique pointer doesn't magically protect you from messing up memory management. Your use case is extremely fishy, and I would caution you to not assume a unique pointer will solve everything and anything.
function expects a modifiable lvalue reference. The call x.get() returns an rvalue. Naturally the reference won't bind to it, no matter how hard you try. Now, the obvious solution is to introduce a temporary:
auto *f = x.get();
function(f);
But that may come back and shoot you in the foot if function needs to actually modify f, the pointer and not the pointee.
Since you mentioned it a comment that it indeed modifies its argument. You must reliniquish ownership from the unique pointer before the call, and give it back after:
auto *f = x.release();
function(f);
x.reset(f);
That is the only way the change will reflect in x. But again, it's still a bit fragile.
The problem here is that the function can modify the pointer you pass to it (passed by non-const reference), potentially re-seating it. If that is the case, then you would have to do something like this:
std::unique_ptr<float[]> x(new float[N]); // remember the array type []
float* fp = x.release();
func(fp);
x.reset(fp);
But the critical point is passing in a proper (named) pointer, not just a temporary pointer returned by x.get().
Your error occurs because the function is unable to modify the temporary pointer returned by the function x.get(). You have to give it a real pointer that can change value.

C++ beginner: what is the point of using a variable by reference if using "const"?

I was wondering about the logic in this function declaration:
CMyException (const std::string & Libelle = std::string(),...
What is the point of using a variable by reference? Usually you pass a variable by reference whenever it may be modified inside... so if you use the keyword const this means it'll never be modified.
This is contradictory.
May someone explain this to me?
Actually reference is used to avoid unnecessary copy of the object.
Now, to understand why const is used, try this:
std::string & x= std::string(); //error
It will give compilation error. It is because the expression std::string() creates a temporary object which cannot be bound to non-const reference. However, a temporary can be bound to const reference, that is why const is needed:
const std::string & x = std::string(); //ok
Now coming back to the constructor in your code:
CMyException (const std::string & Libelle = std::string());
It sets a default value for the parameter. The default value is created out of a temporary object. Hence you need const (if you use reference).
There is also an advantage in using const reference : if you've such a constructor, then you can raise exception like this:
throw CMyException("error");
It creates a temporary object of type std::string out of the string literal "error", and that temporary is bound to the const reference.
Some arguments might use quite some memory. If you pass an argument as value it will be copied and the copy will be passed to the method.
Passing them as reference will only pass the pointer to the method which is faster and saves the memory for the copy.
For example you can only do this with const reference argumernt:
CMyException("foo");
Think about it and then it will become clear.
Passing primitive types (int, char,..) by const reference doesn't make sense. Even for std::string I would argue it's not needed.
However, larger structures or classes require a copy when passing by value, so there's overhead there. A const reference simulates the behavior of passing by value (the outside variable isn't modified), but also prevents the extra copy.
No. It is not always necessary that whenever you pass any variable as reference it is only so that it may be modified inside. If the variable is passed by value then a copy of the variable is made whenever that function is called.
A reference variable on the other hand, uses the same object and essentially passes only the memory address (same as using std::string*, but with the exception that you cannot use a null memory address). So, when you do something like const std::string& x, what you're saying is:
1. The passed argument will not be copied. The same object will be used as in memory.
2. The function will absolutely not modify the object that it is handling.
If you think about it, using const makes sense when you're working with references and not otherwise. If you are making a copy of a variable that I pass and then modifying it, I couldn't really care less. However, it would be really nice to know for a fact that if you're not going to modify the very object I pass (as you will be using the very same object), I can strictly further define the process of my application under this guarantee.
I generally pass everything as const - I never modify the parameters, by value for primitive types, by reference for custom types. Passing by value for primitive types is more efficient in most of the cases - consider an unsigned short - by value 2 bytes, by reference 4-8 bytes depending on the pointer size.

What is the difference when passing by reference between & and *?

When declaring a function, what is the difference between the parameters string* and string&? I know that string s would make a copy of the string s and pass it by value, but it seems that on many websites, they refer to string* s and string& s as both passing by reference. I am new to C++ and this is the only thing that i have not been able to figure out myself. Thanks in advance :)
Decent explanation here:
http://www.cprogramming.com/tutorial/references.html
(Hint: there is more to it than "it looks different")
Passing by pointer string* s passes in an address, so s is not of type string, it's an address. If you dereferenced it, that is used some expression including *s, then *s is of string type.
When passing by reference string& s, s is of type string, so no dereferencing is necessary.
Lots of almost right answers. Many are right for particular implementations but rely on unspecified behavior on the part of a compiler.
Aside from the . vs ->:
pointers are first class objects and references are not. You can take the address of a pointer but you cannot take the address of a reference (you'll get the address of the referenced object)
references always refer to the same object for the duration of their lifetime. Non-const pointers can change.
References cannot be to a "null object". You can write code that does this but you're relying on unspecified compiler behavior
You can do arithmetic on pointers
In general, the language spec says very little about references, purposefully giving compiler writers a lot of latitude in implementaiton. The fact that they operate a lot like const pointers is not guaranteed by the spec.
I find pointer parameters quite useful in two ways:
The caller has to pass a pointer which could very well be the address of an automatic variable. This makes it obvious to the person reading the calling code that the variable whose address is being passed is likely to change.
Pointers can have a NULL value, which acts like a sentinel. References cannot do that. For example, in your own example of string & versus string *, an empty string could be an acceptable value for the variable and hence useless as a sentinel. However, a NULL value for the pointer parameter tells your function that the string * argument was not set by the caller. The function that receives a string & has no way to determine if the caller has not set the value or is content with the default initialized value.
The main difference is how the function will be called. Consider these examples:
void f(string *s)
{}
int main() {
string s;
f(&s);
}
and the reference version:
void f(string &s) { }
int main() {
string s;
f(s);
}
So the function call looks different...
`

Use of the & operator in C++ function signatures

I'm currently reading through Accelerated C++ and I realized I don't really understand how & works in function signatures.
int* ptr=&num;
means that ptr now holds the address to num, but what does that mean?
void DoSomething(string& str)
from what I understand that is a pass by reference of a variable (which means passing the address) but when I do
void DoSomething(string& str)
{
string copy=str;
}
what it creates is a copy of str. What I thought it would do is raise an error since I'm trying to assign a pointer to a variable.
What is happening here? And what is the meaning of using * and & in function calls?
A reference is not a pointer, they're different although they serve similar purpose.
You can think of a reference as an alias to another variable, i.e. the second variable having the same address. It doesn't contain address itself, it just references the same portion of memory as the variable it's initialized from.
So
string s = "Hello, wordl";
string* p = &s; // Here you get an address of s
string& r = s; // Here, r is a reference to s
s = "Hello, world"; // corrected
assert( s == *p ); // this should be familiar to you, dereferencing a pointer
assert( s == r ); // this will always be true, they are twins, or the same thing rather
string copy1 = *p; // this is to make a copy using a pointer
string copy = r; // this is what you saw, hope now you understand it better.
The & character in C++ is dual purpose. It can mean (at least)
Take the address of a value
Declare a reference to a type
The use you're referring to in the function signature is an instance of #2. The parameter string& str is a reference to a string instance. This is not just limited to function signatures, it can occur in method bodies as well.
void Example() {
string s1 = "example";
string& s2 = s1; // s2 is now a reference to s1
}
I would recommend checking out the C++ FAQ entry on references as it's a good introduction to them.
https://isocpp.org/wiki/faq/references
You shouldn't know anything about pointers until you get to chapter 10 of Accelerated C++ !
A reference creates another name, an alias, for something that exists elsewhere. That's it. There are no hidden pointers or addresses involved. Don't look behind the curtain!
Think of a guy named Robert
guy Robert;
Sometimes you may want to call him Bob
guy& Bob = Robert;
Now Bob and Robert both refer to the same guy. You don't get his address (or phone number), just another name for the same thing.
In your function
void DoSomething(string& str)
{
  string copy=str;
}
it works exactly the same, str is another name for some string that exists somewhere else.
Don't bother with how that happens, just think of a reference as a name for some object.
The compiler has to figure out how to connect the names, you don't have to.
In the case of assigning variables (ie, int* ptr = &value), using the ampersand will return the address of your variable (in this case, address of value).
In function parameters, using the ampersand means you're passing access, or reference, to the same physical area in memory of the variable (if you don't use it, a copy is sent instead). If you use an asterisk as part of the parameter, you're specifying that you're passing a variable pointer, which will achieve almost the same thing. The difference here is that with an ampersand you'll have direct access to the variable via the name, but if you pass a pointer, you'll have to deference that pointer to get and manipulate the actual value:
void increase1(int &value) {
value++;
}
void increase2(int *value) {
(*value)++;
}
void increase3(int value) {
value++;
}
Note that increase3 does nothing to the original value you pass it because only a copy is sent:
int main() {
int number = 5;
increase1(number);
increase2(&number);
increase3(number);
return 0;
}
The value of number at the end of the 3 function calls is 7, not 8.
It's a reference which allows the function to modify the passed string, unlike a normal string parameter where modification would not affect the string passed to the function.
You will often see a parameter of type const string& which is done for performance purposes as a reference internally doesn't create a copy of the string.
int* ptr=&num;
1st case: Since ptr is a memory and it stores the address of a variable. The & operator returns the address of num in memory.
void DoSomething(string& str)
2nd case: The ampersand operator is used to show that the variable is being passed by reference and can be changed by the function.
So Basically the & operator has 2 functions depending on the context.
While pass by reference may be implemented by the compiler by passing the address as a pointer, semantically it has nothing to do with addresses or pointers. in simple terms it is merely an alias for a variable.
C++ has a lot of cases where syntax is reused in different contexts with different semantics and this is one of those cases.
In the case of:
int* ptr=&num;
you are declaring a variable named ptr with a type of an int * (int pointer), and setting its value to the "address of the variable num" (&num). The "addressof" operator (&) returns a pointer.
In the case of:
void DoSomething(string& str)
you are declaring the first parameter of the DoSomething() method to be of type "reference to string". Effectively, this is the C++ way of defining "pass-by-reference".
Note that while the & operator operates similarly in these cases, it's not acting in the same way. Specifically, when used as an operator, you're telling the compiler to take the address of the variable specified; when used in a method signature, you're telling the compiler that the argument is a reference. And note as well, that the "argument as a reference" bit is different from having an argument that is a pointer; the reference argument (&) gets dereferenced automatically, and there's never any exposure to the method as to where the underlying data is stored; with a pointer argument, you're still passing by reference, but you're exposing to the method where the variable is stored, and potentially exposing problems if the method fails to do a dereference (which happens more often than you might think).
You're inexplicitly copy-constructing copy from str. Yes, str is a reference, but that doesn't mean you can't construct another object from it. In c++, the & operator means one of 3 things -
When you're defining a normal reference variable, you create an alias for an object.
When you use it in a function paramater, it is passed by reference - you are also making an alias of an object, as apposed to a copy. You don't notice any difference in this case, because it basically is the object you passed to it. It does make a difference when the objects you pass contain pointers etc.
The last (and mostly irrelevent to your case) meaning of & is the bitwise AND.
Another way to think about a reference (albeit slightly incorrect) is syntactic sugar for a dereferenced pointer.