Below is a simple example that produces errors (VS 2019):
E0461 initial value of reference to non-const must be an lvalue
C2664 'void foo(std::string &)': cannot convert argument 1 from 'std::string' to 'std::string &'
using namespace std;
void foo(string& input) {
cout << "Foo is: " << input << endl;
}
string getInput() {
return string("abc");
}
int main()
{
foo(getInput());
}
I don't understand the error. getInput() returns a string. Why can't that string be passed directly to the foo() function as a reference just like any local or member variable can be passed by reference to the foo() function? As the error message suggests, making the string argument a const makes the error go away. Why would that be?
Update: I thought about this question some more after considering the response and a couple links that I posted below. I think the core issue here is that the return value of getInput() is a temporary variable. If I had instead copied the result of getInput() into a local or global variable and then passed that to foo(), there would be no error. I think the compiler does not "like" passing the temporary variable that stores the result of getInput() by reference because how long will the temporary variable stay valid? Obviously, it must stay valid immediately after getInput() returns, but how much longer after that?
This is because a const reference can bind to both lvalue and rvalue. This makes sense as being marked as const, the value cannot be changed even if the input is an rvalue. If the value is not const, you then have the option of editing the non-const reference inside the function. This would make no sense as the input was an rvalue.
Related
EDIT: Sorry, I asked this question without a thro understanding of references...
I seem to be getting this error when I run this code...
error: invalid initialization of non-const reference of type 'std::function&' from an rvalue of type 'main()::'
#include <bits/stdc++.h>
using namespace std ;
void printfunction(bool a, function <void()> &b)
{
if (a == true)
{
b() ;
}
}
int main()
{
int value = 45 ;
printfunction(true, [value](){cout << "The value is : " << value ;}) ;
}
But, the error disappears when I add a const before function... like this :
void printfunction(bool a,const function <void()> &b)
The thing is I would like to change the function in the function reference if needed...
Is there any other way to do this? Please let me know if it does indeed exist.
Bye,
Samuel
In printfunction call, lambda expression [value]() {...} argument must be converted to a temporary function<void()> object first.
A reference to non-const function<void()>& only binds to l-values, not temporaries (r-values).
A reference to const, on the other hand, can be bound to temporaries. Which is what you observe.
If you want to modify the std::function, then you'll need to pass a modifiable (lvalue) parameter:
int main()
{
int value = 45;
std::function f = [value](){ std::cout << "The value is : " << value ;};
printfunction(true, f);
}
What you were trying to do isn't much different from writing a function that takes a mutable reference to int (e.g. void foo(int& x)) and then complaining that you can't call foo(5). (The small difference is that the the lambda-expression is converted to a temporary std::function - but that still can't be bound to a non-const reference).
An alternative would be to change printfunction to take its argument by value rather than by reference, so that it has its own copy which it may modify. You'll have to consider the needs of the caller to decide whether that's more appropriate.
Why does the following program fail to compile:
#include<iostream>
using namespace std;
int fun(int &x)
{
return x;
}
int main()
{
cout << fun(10);
return 0;
}
It gives the following compilation error:
invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
To make it compile successfully , I have 2 options:
1. we have to use "int fun(const int &x)" instead of "int fun(int &x)"
2. use "int i=10;cout << fun(i);" instead of "cout << func (10)"
So, it seems like , if we pass a hard coded value to a function , it will be treated like "const reference".
Am I right here? or is there any other reason that above program doesn't compile?
This doesn't compile because non-const lvalue references cannot bind to rvalues.
Think about it this way: if x in fun is a non-const lvalue reference, we should be able to modify it. However, we have passed in the integer literal 10. What should it mean to modify an integer literal? That doesn't make sense, so you can't.
To fix this, you should take your argument in by reference-to-const (assuming you don't plan on modifying it in fun):
int fun(const int &x)
This is a newbie question but I cannot understand how it works.
Suppose I have the function like the one below
void foo(const std::string& v) {
cout << v << endl;
}
And the call below in my program.
foo("hi!");
Essentially I am passing a const char* to a function argument that is const reference to a string so I have a doubt on this call.
In order to pass an argument by reference, am I right to say that the variable must exist at least for the duration of the call? If it is so, where is created the string that is passed to the function?
I can see that it works : does it happen because the compiler creates a temporary string that is passed to the argument or the function?
does it happen because the compiler creates a temporary string that is passed to the argument or the function?
Yes, and temporaries are allowed to bind to const lvalue references. The temporary string v is alive for the duration of the function call.
Note that this is possible because std::string has a implicit converting constructor with a const char* parameter. It is the same constructor that makes this possible:
std::string s = "foo";
I get the error from xcode (3.2.4)/gcc(4.0):
/Users/admin/scm/audacity/mac/../src/toolbars/DeviceToolBar.cpp: In member function 'void DeviceToolBar::ShowInputDialog()':
/Users/admin/scm/audacity/mac/../src/toolbars/DeviceToolBar.cpp:817: error: no matching function for call to 'DeviceToolBar::ShowComboDialog(wxChoice*&, wxString)'
/Users/admin/scm/audacity/mac/../src/toolbars/DeviceToolBar.h:74: note: candidates are: void DeviceToolBar::ShowComboDialog(wxChoice*, wxString&)
So it looks like it expects a reference to a pointer in ShowComboDialog, but I don't know why as the signatures are clearly normal pointers. Furthermore if it was expecting a reference to a pointer the way I am calling it should work.
This is the first error, and there are no special warnings before it.
Also, this compiles in MSVC 2008 express.
Please give me a clue.
//in the class def
//(only relevant portions included
class DeviceToolBar:public ToolBar {
public:
DeviceToolBar();
virtual ~DeviceToolBar();
void ShowInputDialog();
private:
void ShowComboDialog(wxChoice *combo, wxString &title);
wxChoice *mInput;
};
//in the cpp file
void DeviceToolBar::ShowInputDialog()
{
ShowComboDialog(mInput, wxString(_("Select Input Device")));
}
void DeviceToolBar::ShowComboDialog(wxChoice *combo, wxString &title)
{
//...
}
The problem is not the first parameter; its the second. You're passing in a temporary wxString, but the function is expecting a reference. C++ will automatically convert a temporary to a const reference, but it cannot convert it to a reference. You need to make ShowComboDialog take a const reference as its second parameter.
Your ShowComboDialog takes a wxString by non-const reference and you are trying to pass a temporary object as an argument to this parameter. You can only bind const references to temporary objects.
You either need to change ShowComboDialog to take its second argument either by value (wxString) or by const reference (const wxString&) or you need to create a variable for the wxString that you create when you call the function and then pass (a reference to) that variable instead.
I'm working on Linux gcc environment and I need to initilize function arguments that are classes with default values.
When I do that with temporary instance of the class it makes an error like this: "default argument for [function argument] has type [class name].
for example:
void foo(std::wstring& str = std::wstring())
error: default argument for 'std::wstring& str' has type 'std::wstring'
P.S. this code is compiled without any error or warning with VC++.
How can I initilize the default value?
This is supposed to not compile. You are trying to bind an rvalue to a non-const reference. Say std::wstring const & str and it should work.
You could just create a function overload:
void foo() {
std::wstring str;
foo(str);
}
but I really miss the point.
EDIT:
I mean, that function's purpose is almost certainly to modify an input string. If you provide an empty input string that you can't access later, why bother?
You cannot bind non-const references to rvalues. Passing by value would work:
void foo(std::wstring str = std::wstring())
Or passing by reference-to-const:
void foo(const std::wstring& str = std::wstring())