I'm trying to get the following line to compile, but i'm suffering from pointer confusion:
int test = _s->GetFruitManager()->GetFruits()[2].GetColour();
std::cout << test << std::endl;
where _s is a pointer to S, and GetFruitManager() returns a pointer to a FruitManager object, GetFruits() returns a std::vector<Fruit>* and i then want to be able to use the operator [] to acess a specific Fruit object and call the Fruit's GetColour() method.
I think at some point i need to dereference the vector* returned by GetFruits() but i can't figure out how.
Apologies if this is somewhat convoluted! i'm still quite new to the language, but would appreciate some help clearing this up. I did try to break it down into more digestible steps but was unable to get it to compile either way.
I've actually just decided not to use this code snippet anyway, but it's become a matter of curiosity so i'll still submit the question anyway :)
You need to do this:
(*(_s->GetFruitManager()->GetFruits()))[2].GetColour();
As an alternative to using the [] syntax, you can invoke .at():
int test = _s->GetFruitManager()->GetFruits()->at(2).GetColour();
The ugly edition:
int test = _s->GetFruitManager()->GetFruits()->operator[](2).GetColour();
Yes, you need to dereference the pointer returned by GetFruits():
int test = (*_s->GetFruitManager()->GetFruits())[2].GetColour();
FruitManager* temp_ptr = _s->GetFruitManager();
std::vector<Fruit>* ptr_vec = temp_ptr->GetFruits();
Fruit* f_obj_ptr = (*ptr_vec)[2];
int test = f_obj_ptr->GetColour();
Even though the correct answer has been posted, I would prefer a version like that cause it is more readable. And when you come back 2 days later, you can find a bug/do a fix much easier/faster.
Since no one mentioned it, there is also this alternative (which I personally like to use in gdb only):
int test = _s->GetFruitManager()->GetFruits()[0][2].GetColour();
Related
what does this C++ code snippet do?
IEntity* wLocalEntity= const_cast<IEntity*>(BaseSimSystem::getEntityRef());
if(wLocalEntity!=0){
mEntitySpeed=wLocalEntity->getSpeed();
}
I'm not sure how it's related to a template creation. Can someone explain to me what this code does?
Thank you.
Here's the code.
IEntity* wLocalEntity= const_cast<IEntity*>(BaseSimSystem::getEntityRef());
if(wLocalEntity!=0){
mEntitySpeed=wLocalEntity->getSpeed();
}
If you actually get asked about this code, the first thing I'd do is complain about the if-clause. that 0 should be nullptr as so:
if (wLocalEntity != nullptr) {
mEntitySpeed = wLocalEntity->getSpeed();
}
Also, please tell me you know you shouldn't compress your code so tightly. Bugs hide when you shove all those operators together with no whitespace.
Now, let's look at line 1:
IEntity* wLocalEntity = const_cast<IEntity*>(BaseSimSystem::getEntityRef());
Clearly, wLocalEntity is a pointer to an IEntity. I hope you understood that.
The const_cast<> bit is ridiculous and possibly a bug. We don't know what BaseSimSystem::getEntityRef() returns, but I suspect it returns a const pointer, and now you're trying to assign that back to a non-const variable. The const_cast<> is getting rid of the constness.
The correct code is almost certainly:
const IEntity * wLocalEntity = BaseSimSystem::getEntityRef();
However, it's possible that IEntity has methods that aren't flag const that really should be, so you might have to do this because some other programmer didn't apply const when he should have.
So the const_cast<IEntity *> says "take the return value in those parenthesis and yes, I know they're not a non-const IEntity *, but don't warn me about it because supposedly I know what I'm doing.
How's that?
Take for example:
int main(void){
numberComparator comparator1;
comparator1.setA(78.321);
comparator1.showA();
comparator1.setB('c');
comparator1.setB("Yes");
comparator1.setB(124.213);
comparator1.showB();
comparator1.setB(12);
return 0;
}
Instead of saying comparator1 over and over again, can I do something shorter?
I understand that this doesn't really change much about how the program works, but it does make it easier to work around with testing a class I make.
I am doing overloading so that for an assortment of inputs into my comparator, my program can handle them without making the results go crazy. In this case, I want the input to be an int, but what if the input isn't?
The answer could be lying around the internet, but as my title may infer, I do not know how to state the question.
You are looking for something like with keyword which is part of, for example, Pascal language.
Unfortunately, C++ doesn't provide similar feature. Using the references, one can shorten the name of the class and somewhat alleviate the pain, i.e.
Comparator comparator1;
...
{
Comparator& cr = comparator1;
cr.a();
cr.b();
cr.c();
}
It depends. If numberComparator has a "fluent" interface, then each member function will return a reference to *this, and you can write:
comparator1
.setA(78.321)
.showA()
.setB('c')
.setB("Yes")
.setB(124.213)
.showB()
.setB(12);
Note that this is a bitch to debug by step-into (you have to step into every function until you get to the one you are interested in).
The alternative of course is "use a shorter name".
int main(void){
numberComparator c1;
c1.setA(78.321);
c1.showA();
c1.setB('c');
c1.setB("Yes");
c1.setB(124.213);
c1.showB();
c1.setB(12);
return 0;
}
There is really no point in having a particularly long name if it is limited in scope to a few lines. For a local variable, if it isn't limited in scope to a few lines, your function is probably too long.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am using box2d(however this question is probably only about c++ itself) and there is a member variable which is pointer to void, like this:
void* userData;
You can get the userData by the getUserData(), which returns a a void pointer.
I want to store a string as the userData and there is set the userData to the string like so:
std::string user = "player";
playerDef.userData = &user;
Then I am trying to get the userData by doing this:
std::string* sd = (std::string*)bb->GetUserData();
(where "bb" is a pointer to the entity holding these information)
Finally, I try to use the function c_str() in order to get what is compatible for my purposes but then I get the error:
Access violation reading location 0x00000070
I also want to be able to do the same thing but with a char array but I am doing this:
char user[] = "player";
playerDef.userData = &user;
char* sd[] = (char*)bb->GetUserData();
The third step gives the error:
Cannot convert from 'char' to 'char*[]'*
I could already feel by looking at this approach on the char part that something was wrong but I do not know what...
I did the same thing with integers like this:
int user[] = int;
playerDef.userData = &user;
int* sd = (int*)bb->GetUserData();
and that worked just great.
So my questions are the following:
What am I doing wrong with the std::string part?
What is wrong with the char part and how to achieve the char array
that I want?
How come that the integer part works then :/ (I know that it is not an array though)?
Note: I would be more than happy to get extra thoughts on possible optimizations in general, like user static_cast or something.
Thanks! It is really appreciated, like very much!
Cheers.
std::string user = "player";
playerDef.userData = &user;
When whatever function sets this pointer here returns, user, the std::string object, gets destroyed. The fact that there's a pointer to this std::string, somewhere, doesn't change that.
Your subsequent attempt to use this pointer fails miserably, since, obviously, the string has been destroyed, and the pointer points to garbage.
And when you use an int array, that was broken also. The fact that your program didn't crash in that case doesn't change that this was undefined behavior, and a bug.
This is a common situation when integrating C++ code with a generic C library, that knows nothing about C++ classes, where all that it offers you to work with is an opaque, bland void pointer. There are several ways of doing this correctly. A common way is to use dynamic scope:
playerDef.userData = new std::string;
*playerDef.userData = "player";
Later you can dereference this pointer, having some degree of confidence that the pointed-to object still exist, and hasn't been nuked from high orbit.
Of course, now you will need to make sure that at some point this is going to get deleted, otherwise you'll leak memory. But this is often the best that can be done when working with a C library's opaque pointers.
this is more like an ethical question:
if i have the following code:
void changeInt(int& value)
{
value = 7;
}
and i do:
int number = 3;
changeInt(number);
number will have value 7
I know that when the new stack frame will be created for changeInt function, new variables will be created and &value will point to number.
My concern here is that the caller, if it's not paying attention , can be fooled by thinking that is passing by value which actually, on the function frame , a reference will be created.
I know he can look in the header files and it's a perfect legitimate expression but still I find it unethical a bit :)
i think this should be somehow marked and enforced by syntax. Like in C# where you have ref keyword.
What do you guys think ?
This is one of those things where references are less clear than pointers. However, using pointers may lead to something like this:
changeInt(NULL);
when they actually should have done:
changeInt(&number);
which is just as bad. If the function is as clearly named as this, it's hardly a mystery that it actually changes the value passed in.
Another solution is of course to do:
int calculateNewInt(/* may need some input */)
{
return 7;
}
now
int number = 3;
...
number = calculateNewInt();
is quite obviously (potentially) changing number.
But if the name of the function "sounds like it changes the input value", then it's definitely fair to change the value. If in doubt, read the documentatin. If you write code that has local variables that you don't want to alter, make them const.
const int number = 3;
changeInt(number); /* Makes an error */
(Of course, that means the number is not changeable elsewhere either).
I know he can look in the header files and it's a perfect legitimate expression but still I find it unethical a bit :)
I think that's perfectly normal and part of the language. Actually, this is one of the bad things of C and C++: you have to check the headers all the time when dealing with an unknown API, since when calling a function you don't pass by reference explicitly.
That's not the case for all system languages though. IIRC Rust makes it obligatory to pass references explicitly.
To me it seems like it should be so simple, but I just feel like I'm missing something.
I have in my header file a private variable _stoplist When I declared it in the header file the code looks just like this.
private:
std::string _stoplist[];
But when later in my function I decide to access this, it segfaults on anything.
_stoplist[_length];
//cout << _length << prints 104 (its a valid int and everything)
_stoplist[0] = "b";
Crashes in the std::string.assign() code with a segfault. I have a gut feeling that I'm missing something obvious here but I haven't quite found out what yet.
Thanks in advance!
EDIT: Ok, thanks for all the help. For anyone else who may read this, I would recommend to use one of the answers below since that is the smart way to do it. In my case though since I needed to dynamically allocate it without using vector I just used the following code.
private:
std::string *_stoplist;
and then in my cpp file
_stoplist = new string[_length];
Yeah, turns out that it really was way simple, and I just was over looking that part.
You're getting an array out of bounds error because _stoplist doesn't have a size. You should either give it a size, and only access elements within that range, such as:
private:
std::string _stoplist[100];
now you should be able to index _stoplist[0] through _stoplist[99]. However a better solution would probably to use std::vector instead, as it's a lot safer.
private:
std::vector< std::string > _stoplist;
Then you can use its member functions such as resize() to grow it to whatever size you need.
That's because a variable declared as std::string[] is basically just a pointer. To use it, you need to allocate memory for it. If you want to allocate fixed memory for it, try declaring it as e.g. std::string _stoplist[5]; instead.