I have a function like this:
int find_string ( string *url){
if(*url.find() != string::npos){
[...]
}
[...]
}
And call it this way:
find_string(&url);
But I got the following compiling error:
request for member ‘find’ in ‘url’, which is of non-class type ‘std::string*’
Why this happen and, most importantly, how can I fix this? (When there was no pointer, it was working)
*url.find() is equivalent to *(url.find()) when what you actually want is (*url).find(). Better yet you should be using url->find() instead.
The reason for this is the dereference (*) operator has lower precedence than the element selection (.) operator.
use (*url).find() or, better url->find()
*url.find tries call find() function and then use operator *
Related
I want to know if it's possible to return a pointer while initializing it. I know that we can use string s("Hi") to declare and initialize a string s, but can we do the same for a pointer?
What I'm trying to do is keep my code as minimal as possible to try to learn to optimize my code, so I tried queue<string> *p(&item) where item is a queue<string>. This works; however, adding return results in the error "Expected primary-expression before *".
My code snippet:
struct parsedObj
{
queue<string> item;
bool operator!() {return !item.empty();}
queue<string>* operator*() {return queue<string> *p(&item);}
};
I want to know if it's possible to return a pointer while initializing it
You always initialize the return value. There is no way to not initialize it. (Well, you could forget to write the return statement, but that makes the program ill-formed).
but can we do the same for a pointer?
Yes.
adding return results in the error "Expected primary-expression before *".
This limitation applies to non-pointers as well. You cannot write return string s("Hi") either for example.
The syntax of return statement is attr(optional) return expression(optional). A declaration is not an expression. string s("Hi") and queue<string> *p(&item) are declarations.
Simply use
return &item;
to return a pointer. There's no need to declare any variables in that function.
PS. It seems quite perverse to return a pointer to a member from the indirection operator. Conventionally the indirection operator does the opposite (i.e. the operand of the indirection is a pointer, and the result is the pointed object).
I used this instead and it did the job better than having a pointer:
queue<string>* operator->() {return &item;}
This is not the solution, this is just a tip. Now I can use parsedObj-> which simplifies the process.
If I have a std::vector, I can access a member because the square bracket operator is overloaded in the vector class. If I have a pointer to a vector, I can dereference the pointer and use this operator. But with the arrow -> operator it won't let me use it. Example:
// Excuse the UB here, it's just for illustration
std::vector<int> myVector;
std::vector<int>* pToVector;
myVector[4] = 0; // Works fine
(*pToVector)[4] = 0; // Works fine
pToVector->[4] = 0; // Doesn't work
(pToVector->)[4] = 0; // Doesn't work
Seeing as though the -> arrow operator dereferences the pointer, is there a reason not to expect that this would work? Or is it just one of those things about the language?
Thanks.
std::vector<int> myVector;
std::vector<int>* pToVector;
myVector[4] = 0; // Works fine.
(*pToVector)[4] = 0; // Works fine
pToVector->[4] = 0; // Doesn't work
(pToVector->)[4] = 0; // Doesn't work
If you must use a pointer to an object to access an overloaded operator of the object's class, you will have to call it explicitly.
pToVector->operator[](4)
... By the way, Accessing an index outside myVector.size() is Undefined Behavior. This includes the statements with the comment annotation in your code about // Works fine.
The correct syntax for the second two lines would be:
(*pToVector)[4] = 0;
//dereference the pointer and then call operator[] on the object returned by the dereference
You could use the -> operator to access regular member functions like this:
pToVector->size();
Technically you could try yo call the operator[] by name but it is more verbose.
The reason is that [] is an operator, and the short operator syntax does not require or allow member access operators. This applies to both member access operators . and ->, which makes sense because the latter is just shorthand for (*a).b.
E.g. all disallowed a. & b, a->^b
Technically, it also applies to the rarer .* and ->*. Note that the latter is not -> followed by operator*, but a pointer to member pointer dereference.
-> operator is replacement for dot operator, except it dereferences a pointer first. It is used to access attributes(members and functions). For your operation, operator[] is the attribute. So, pToVector->operator[](4) is applied to (*pToVector)[4] = 0
The -> operator does not just dereference, it also accesses a member. You are accessing an element*, not a member. -> could have been defined to allow that, but wasn't.
* To be more precise, a vector is letting you access an object as if it were an element of an array, but it doesn't change the syntax.
I think the square brackets dereference the pointer, so you ended up dereferencing twice there.
ptoVector[4] I think would have worked and been sufficient since the square brackets do a dereference for you.
I was looking over the following code:
string toUpper(string s) {
string result;
int (*toupperp)(int) = &toupper; // toupper is overloaded
transform(begin(s), end(s), back_inserter(result), toupperp);
return result;
}
I am confused by this line:
int (*toupperp)(int) = &toupper; // toupper is overloaded
1.Why is this line necessary?
2.I believe that & retrieves a pointer to something from memory. But toupper, the name of the function is already a pointer, no? Why can't we do this:
int (*toupperp)(int) = toupper;
3.Why is the function overloaded to int if it's used on a string?
1) It's not necessary, really. If you have used using namespace std directive, it's necessary to cast to the desired type to let the compiler know which overload you want. So, you might also say
transform(begin(s), end(s), back_inserter(result), static_cast<int(*)(int)>(&toupper));
Otherwise the following should be enough:
transform(begin(s), end(s), back_inserter(result), ::toupper);
2) Identifiers that are function names decay into pointers, yes, but they aren't exactly the same thing. That being said, in this case it should be fine to say
int (*toupperp)(int) = toupper;
or even (if you haven't used using namespace std directive):
auto toupperp = toupper;
3) it's for compatibility with C standard library. It's used on every element of s, which for string is a char.
What you are passing to transform is a pointer to the function toupper (see function pointers). You store this pointer into the local variable toupperp. The type of toupperp is a pointer to a function taking an int as argument and returning an int.
Unless toupper is defined in strange ways, the function is seemingly used by transform to change each input character to uppercase. Each single character is processed as an integer (with an implicit cast if needed).
Regarding your question 2, using the operator & you make more explicit you are taking the address of the function, but indeed you could omit it. See here (I learnt something today).
If toupper was overloaded, using the intermediate variable is a safe way to get exactly the desired overload. If the desired overload goes away this method will catch the problem at compile time. See here. (And that's something else I learnt today).
This is a follow up question to my previous post: C++: Initializing Struct and Setting Function Pointer
My new question is how do I call a pointer-to-member function within a struct? I have modified my previous code to:
float MyClass::tester(float v){
return 2.0f*v;
}
struct MyClass::Example{
float(Scene_7::*MyFunc)(float);
float DoSomething(float a){
return (MyFunc)(a); //ERROR, SEE BELOW FOR OUTPUT
}
};
I then set the function as follows, and output the result to the call:
struct Example e;
e.MyFunc = &MyClass::tester;
std::cerr << e.DoSomething(1.0f) << std::endl;
I get the following error: must use '.' or '->' to call pointer-to-member function...
The problem is I don't know how to do this. I am guessing I have to call something like this->*(myFunc)(a) within DoSomething but this references the struct. I have tried searching "this within struct pointer-to-member function" but have not been able to find anything. Any help or suggestions would be great. I feel like I am close but it is just a matter of syntax at this point.
The operator precedence of .* and ->* is, IMHO, broken. You need to wrap the operands in parentheses in order to call.
return (this->*MyFunc)(a);
Otherwise, the compiler thinks you're doing this->*(MyFunc(a)), which is obviously invalid.
Interestingly enough, (this->*MyFunc) as a standalone expression is also invalid. It needs to be called on the spot.
I cant tell if you have other errors, do to the lack of code, but you are calling a member function the wrong way, you call them like this:
return (obj->*MyFunc)(6);
I am not sure if you can use this in place of obj on the line above, since from the declaration, you need a pointer to an object of type Scene_7, so you will need to know a pointer of the correct type at that spot in the code..
Remember that . operator has higher precedence than the * operator. So when dealing with pointes and structs etc you will need to use paranthesis or -> operator which means that the pointer points to what.
This question already has answers here:
What can I use instead of the arrow operator, `->`?
(7 answers)
Closed 5 years ago.
What is the difference between the dot (.) operator and -> in C++?
foo->bar() is the same as (*foo).bar().
The parenthesizes above are necessary because of the binding strength of the * and . operators.
*foo.bar() wouldn't work because Dot (.) operator is evaluated first (see operator precedence)
The Dot (.) operator can't be overloaded, arrow (->) operator can be overloaded.
The Dot (.) operator can't be applied to pointers.
Also see: What is the arrow operator (->) synonym for in C++?
For a pointer, we could just use
*pointervariable.foo
But the . operator has greater precedence than the * operator, so . is evaluated first. So we need to force this with parenthesis:
(*pointervariable).foo
But typing the ()'s all the time is hard, so they developed -> as a shortcut to say the same thing. If you are accessing a property of an object or object reference, use . If you are accessing a property of an object through a pointer, use ->
Dot operator can't be overloaded, arrow operator can be overloaded. Arrow operator is generally meant to be applied to pointers (or objects that behave like pointers, like smart pointers). Dot operator can't be applied to pointers.
EDIT
When applied to pointer arrow operator is equivalent to applying dot operator to pointee e.g. ptr->field is equivalent to (*ptr).field.
The arrow operator is like dot, except it dereferences a pointer first. foo.bar() calls method bar() on object foo, foo->bar calls method bar on the object pointed to by pointer foo.
The . operator is for direct member access.
object.Field
The arrow dereferences a pointer so you can access the object/memory it is pointing to
pClass->Field
pSomething->someMember
is equivalent to
(*pSomething).someMember
Use -> when you have a pointer.
Use . when you have structure (class).
When you want to point attribute that belongs to structure use .:
structure.attribute
When you want to point to an attribute that has reference to memory by pointer use -> :
pointer->method;
or same as:
(*pointer).method
The target.
dot works on objects; arrow works on pointers to objects.
std::string str("foo");
std::string * pstr = new std::string("foo");
str.size ();
pstr->size ();
Note that the -> operator cannot be used for certain things, for instance, accessing operator[].
#include <vector>
int main()
{
std::vector<int> iVec;
iVec.push_back(42);
std::vector<int>* iVecPtr = &iVec;
//int i = iVecPtr->[0]; // Does not compile
int i = (*iVecPtr)[0]; // Compiles.
}
It's simple, whenever you see
x->y
know it is the same as
(*x).y
The -> is simply syntactic sugar for a pointer dereference,
As others have said:
pointer->method();
is a simple method of saying:
(*pointer).method();
For more pointer fun, check out Binky, and his magic wand of dereferencing:
http://www.youtube.com/watch?v=UvoHwFvAvQE
The simplest difference between the two is that "->" dereferences a pointer before it goes to look at that objects fields, function etc. whereas "." doesn't dereference first. Use "->" when you have a pointer to an object, and use "." when you're working with the actual instance of an object.
Another equivalent way of wrinting this might be to use the dereferencing "*" on the pointer first and then just use the ".". We skip middleman by using "->".
There are other differences, but the other answers have covered this extensively.
If you have a background in Java this might confuse you, since, in Java, everything is pointers. This means that there's no reason to have symbol that doesn't dereference your pointer first. In c++ however you gotta be a little more careful with remembering what is and what isn't a pointer, and it might be a good idea to label them with the prefix "p_" or simply "p".
The . (dot) operator is usually used to get a field / call a method from an instance of class (or a static field / method of a class).
p.myField, p.myMethod() - p instance of a class
The -> (arrow) operator is used to get a field / call a method from the content pointed by the class.
p->myField, p->myMethod() - p points to a class
The -> operator is used when we are working with a pointer and the dot is used otherwise.
So if we have a struct class like:
struct class{ int num_students; int yr_grad; };
and we have an instance of a class* curr_class (class pointer), then to get access to number of students we would do
cout << curr_class->num_students << endl;
In case we had a simple class object , say class_2016, we would do
cout << class_2016.num_students << endl;
For the pointer to class the -> operator is equivalent to
(*obj).mem_var
Note: For a class, the way to access member functions of the class will also be the same way