My code is the following:
void parentheses (int n, string& str, int left, int right){
... irrelevant...
}
void solve(int n){
parentheses(n,"",0,0);
}
However, this will give me an error, telling me that cannot bind non-const lvalue reference of type std::__cxx11::string& ... to an rvalue of type ‘std::__cxx11::string. In this case, if I still want to pass the string in as a reference, how should I modify my functions? I don't want to make them const because I want to functions to modify the original string, and I want them to be & precisely because I want to edit their values.
The function parentheses expects an lvalue in the std::string parameter, i.e. a named variable. However, you have supplied an rvalue (temporary) in this call:
parentheses(n,"",0,0);
An empty string object is created and passed to parentheses. You can avoid this problem by changing the definition of parentheses like so:
void parentheses (int n, const string& str, int left, int right)
Here str will bind to an rvalue/temporary, but you won't be able to change its value in the function. However, if you want to change the value of str you have to define a string variable and pass that to the function.
Example:
void solve(int n){
std::string str;
parentheses(n,str,0,0);
}
Note: no need to assign str to "" as a string is empty by default.
the function needs a memory to change, you didn't specify which.
declare a string to hold what you want to pass and where to get the output to.
string s = "";
and pass it to the function
I'm not really sure what the purpose is of passing "" by reference is, as any value put there will get lost.
Anyway, to answer your question, create a variable and pass it instead:
void solve(int n){
std::string tmp = "";
parentheses(n,tmp,0,0);
}
If you don't care about the value stored in tmp, you can just ignore it. But you need some type of variable there, even if you don't care about what gets eventually put there by the routine.
Your parentheses() function takes a non-const reference to a std::string object, so it expects an actual std::string object on the other side of the reference - an lvalue (something that can be assigned to).
But your solve() function is not passing a std::string object, it is passing a string literal instead. So the compiler creates a temporary std::string object - an rvalue - which then fails to bind to the reference, because a temporary object can't be bound to a non-const reference, only to a const reference. That is what the error message is telling you:
cannot bind non-const lvalue reference of type std::__cxx11::string& ... to an rvalue of type ‘std::__cxx11::string
solve() needs to explicitly create an actual std::string object to pass to parentheses():
void solve(int n){
std::string s = "";
parentheses(n,s,0,0);
}
If you want to change the values of your string for any string that is passed as a paramenter (lvalue, as well rvalue), just initialize a variable with the intended content and pass it to your function.
But if you want to treat lvalue strings diferently from rvalue strings, just overload your original function. i.e.:
void parentheses (int n, string& str, int left, int right){
... irrelevant... // change strings values as desired
}
void parentheses (int n, string&& str, int left, int right){
... irrelevant... // string as rvalue
}
Related
I want to know is it mandatory to have constant arguments in the functions.
Recently I had in interview and wrote a code like below
int numofsubstring(string s1, string s2)
{
int nCount =0;
size_t pos;
while((pos = s1.find(s2)) != string::npos)
{
nCount++;
s1 = s1.substr(s1.find(s2)+s2.length());
}
return nCount;
} //number of times s2 is present in s1
The panel was expecting const string&s1 ,const string&s2 but i didn't wrote bcz of substr functionality usage...
can any one guide what's the standardised format to write the code....
the panel was insisting to improve the arguments in the function.
To the extent that there is "a rule" the rule would be
if you have some function that takes a T and you can pass a const T& instead without affecting correctness then you should pass a const T&.
It's about eliminating unnecessary copies. Passing a references is like passing a pointer. Nothing gets copied so the performance of the function will be better.
No it is not mandatory to have constant arguments in the functions. Note that the function you wrote is using pass by value. While if you had function parameters as const std::string& then it is pass by reference.
One of the reason for using const std::string& version is that in this case there will be no "copying" of passed strings, so it is faster(for very long strings) than the pass by value version.
Also in the case of pass by value the arguments passed will be copied and each of the argument will be destroyed after the function scope ends. This destruction part will not happen in the pass by reference version.
Edit:
If you want that the arguments passed to the functions should not be changed inside the function body then you can add const. Below is the way to make the arguments const that is they cannot be changed inside the function body anymore.
WAY 1
//pass by value, now that we have added const the arguments s1 and s2 cannot be changed inside the function body
int numofsubstring(const string s1, const string s2)
{
//some code here
}
WAY 2
//pass by reference, now that we have added const the arguments s1 and s2 cannot be changed inside the function body
int numofsubstring(const string& s1, const string& s2)
{
//some code here
}
I am trying to push a string in a string vector, like below
void Node::set_val(string &val)
{
this->val.push_back(val);
}
But when I try to call it as below
Obj.set_val("10h;");
I get the below error,
error: no matching function for call to 'Node::set_val(const char [5])'
I assumed that the string in " " is same as string in c++, Why do I get such an error? What has to be changed below?
You are taking in a std::string by non-const reference. Non-const references cannot bind to rvalues, like "10h;", so you can't pass literals in to that function.
If you aren't going to modify the argument, you should take your argument by reference-to-const:
void Node::set_val(const string &val)
// ^^^^^
This way, a temporary std::string will be constructed from your const char[5] and passed in to set_val.
You could improve this by taking in the string by value and moveing it into the vector:
void Node::set_val(string val)
{
this->val.push_back(std::move(val));
}
This prevents you from making some unnecessary copies.
So in C++, const char* is implicitly convertible to std::string because std::string has a (non-explicit) constructor that takes const char*. So what the compiler tries here is to create a temporary std::string object for your function call, like so:
Node.set_val(std::string("10h;"));
However, since you declared the parameter of set_val to be a non-const reference to a std::string, the compiler can't make this conversion work due to the fact that temporary objects can't be bound to non-const references.
There are three ways to make this work, depending on what you want to achieve:
void Node::set_val(const std::string& val) {}
void Node::set_val(std::string val) {}
void Node::set_val(std::string&& val) {}
All will compile (the last one requires C++11 or higher), but seeing your use case, I would recommend to use the second or third one. For an explanation why, try reading a little bit about move semantics in C++11.
The important thing to take away here is that const char* implicitly converts to std::string by creating a temporary object, and temporary objects can't be passed to functions taking non-const references.
You are passing "10h;" which is a const char array.
Fix it by passing a string: Obj.set_val(string("10h")); and edit function to take a string by value:
void Node::set_val(string val) { /* */ }
Or maybe better, edit your function to take a const string&:
void Node::set_val(const string &val) { /* */ }
I'm using boost::property_tree::ptree and parse_ini to read an ini file. Using ptree::iterator I'm getting the ini sections and want to use them to create another object.
I have an object called First that gets First(int& i, string& str)
So I'm trying to build new object like that using the return values I get from the ptree functions for example (posision is my ptree::iterator)
First* one = new First(
boost::lexical_cast<int>((posision->second).get<int>("number")),
(posision->second).get<string>("name")
);
but I get
no matching function for call to ‘First::First(int, std::basic_string<char>)’
so I tried casting like this:
First* one = new First(
(int&) boost::lexical_cast<int>((posision->second).get<int>("number")),
(string&) (posision->second).get<string>("name")
);
but then I got
invalid cast of an rvalue expression of type ‘int’ to type ‘int&’
and
invalid cast of an rvalue expression of type ‘std::basic_string<char>’ to type ‘std::string&
will appreciate any help or explanation.
thanks !
The issue is that you cannot pass r-values where the argument is typed as an l-value reference. E.g.
void foo(int& x)
{
x = 2;
}
int main(void)
{
foo(5); // won't compile; can't pass r-value to reference parameter
}
If this were valid, we would be assigning the value 2 to the value 5, which is nonsense. If it's possible, you can declare the First constructor to take const references (not sure if this works for you since you didn't post the code):
First(const int& i, const string& str);
Although for primitives, it's best to just pass as value instead of const reference:
First(int i, const string& str)
If you need them to be non-const references (which smells like a bad design), you can do:
int i = boost::lexical_cast<int>((posision->second).get<int>("number"));
string str((posision->second).get<string>("name"));
First* one = new First(i, str);
I have a function defined as:
void func(string & str_alias)
{...}
And in my main function
int main()
{
string a;
func((a="Cat said: ")+"Meow");
}
The compiler would report that
no known conversion for argument 1 from ‘std::basic_string<char>’ to ‘std::string& {aka std::basic_string<char>&}’
Though I know if I change the main function into:
int main()
{
string a;
func(a=((a="Cat said: ")+"Meow"));
}
The code would pass with no issues. But I still wonder why the returned string cannot be passed to the function as a reference. Why do I have to assign it to another string variable?
Thanks.
As long you don't need to change the passed reference, you could easily avoid this by changing your function signature to
void func(const string & str_alias)
// ^^^^^
{...}
and simply call
func(string("Cat said: ") + "Meow");
(see live demo)
If you'll need to change the reference parameter, you must have an lvalue to be modified. Nevertheless writing
func(a=string("Cat said: ")+"Meow");
is sufficient (see the live demo).
If you make it take const reference to std::string, it should compile.
This is because the last thing you do in the first function call is calling std::string operator+(const std::string&, const char*), which as you see returns std::string, not reference, and since it not stored anywhere, it is rvalue, which can't be bound to lvalue-reference.
The second example compiles, because the last thing you do is assign it to the variable a, which calls std::string& operator=(const char*), which as you can see returns reference, so it can be used as non-const reference by itself.
Thanks to 0x499602D2 for correction.
A reference defines an alternative name for an object. A reference type “refers to”
another type. We define a reference type by writing a declarator of the form &d,
where d is the name being declared.
The next thing is a reference is not an object. Instead, a reference is just another name for an already existing object. So we'll use these references to pass the parameter by reference so that it directly effect the actual parameters.
Question:
What happens when we use a reference (&) before a function name?
I'm a little bit confused, as in my opinion it will return the alias of return (variable name). Or am I wrong?.
std::vector<std::string> &split(const std::string &s, char delim,
std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
In C++, when the ref-sign (&) is used before the function name in the declaration of a function it is associated with the return value of the function and means that the function will return by reference.
int& foo(); // Function will return an int by reference.
When not used within a declaration context, putting the ref-sign before a function name results in calling the address-of operator returning the address of the function. This can be used to e.g. create a pointer to a function.
// Some function.
int sum(int a, int b) {
return a + b;
}
int main() {
// Declare type func_ptr_t as pointer to function of type int(int, int).
using func_ptr_t = std::add_pointer<int(int, int)>::type;
func_ptr_t func = ∑ // Declare func as pointer to sum using address-of.
int sum = func(1, 2); // Initialize variable sum with return value of func.
}
In C, the only use of & is for the address-of operator. References does not exist in the C language.
In C, &func where func is a function evaluates to the address of the function which can be assigned to a function pointer which points to a function having the same signature as the function func.
int func(float);
int (*fp)(float) = &func;
// equivalent to
int (*fp)(float) = func;
'// return the plural version of word if ctr is greater than 1
string make_plural(size_t ctr, const string &word,
const string &ending)
{
return (ctr > 1) ? word + ending : word;
}'
The return type of this function is string, which means the return value is copied to
the call site. This function returns a copy of word, or it returns an unnamed
temporary string that results from adding word and ending.
As with any other reference, when a function returns a reference, that reference is
just another name for the object to which it refers. As an example, consider a function
that returns a reference to the shorter of its two string parameters:
'// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string
&s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}'
The parameters and return type are references to const string. The strings are
not copied when the function is called or when the result is returned.
Never Return a Reference or Pointer to a Local Object
When a function completes, its storage is freed. After a function
terminates, references to local objects refer to memory that is no longer valid: