I have written the following code:
#include "joinCommand.h"
joinCommand::joinCommand(map<string, Task *>* threadMap) {
this->threadMap=threadMap;
}
string joinCommand::execute(vector<string> args) {
if(threadMap->count(&args.at(1)) ==1){
Task* t= this->threadMap["fkjk"];
}
}
The compiler gives an error message for the following line:
Task* t= this->threadMap["fkjk"];
The error message is:
array index is not integer.
How am I supposed to get the value of Task* from the map?
The problem here is a little subtle... threadMap is accessible by this->threadMap, but it's also a pointer. The type of this->threadMap is map<string, Task *> * not map<string, Task *>, so when you do the [] operator on it, it's acting on the pointer and not on the dereferenced object.
You would need to do this:
Task* t= (*this->threadMap)["fkjk"];
More explicitly:
Task* t= (*(this->threadMap))["fkjk"];
Alternatively you can directly call the brackets operator with the arrow syntax:
Task* t= this->threadMap->operator[]("fkjk");
As another alternative, you can use stl map's named methods instead of overloaded operators:
Task* t= this->threadMap->at("fkjk");
Read the documentation here:
http://www.cplusplus.com/reference/map/map/
This all being said and done, I suggest you use STL map's find() method to return an iterator, and check it for validity then dereference that instead, something like this:
map<string, Task*>::iterator it = this->threadMap->find(&args.at(1));
if (it != this->threadMap->end()) {
Task *t = *it; // or just directly use *it or it->
// continue to use the valid 't' pointer
}
From the first function I guess this->threadMap is a pointer because you assign another pointer to it. This guess well complies with the error message.
So the solution is to dereference the pointer before using functions from std::map:
(*this->threadMap)["fkjk"];
Related
Supposing that I have a class called TextEntry with some instance variables and a method ask() (which returns an integer).
I then create a vector of type: std::vector<TextEntry*> d_text (a vector of pointers of type TextEntry). I wish to iterate over all the elements in this vector and call the method ask() applied to each element. Is this the correct way to do it?
for (std::vector<TextEntry*>::iterator it = d_text.begin(); it != d_text.end(); ++it) {
TextEntry* TextEntryPointer = *it; // first dereference the iterator
TextEntry TextEntry = *TextEntryPointer; // dereference the TextEntry pointer
int j = TextEntry.ask();
}
For whatever reason this implementation is giving me an error so it would be helpful to know if the reason why is because of the above code or some other problem in the rest of my project.
I wish to iterate over all the elements in this vector and call the method ask() applied to each element. Is this the correct way to do it?
Almost.
Your program doesn't call ask on any element pointed by d_text but on a copy of each pointed element.
I am confused why it is a copy.
You create a variable of type TextEntry. You copy-initialize it from *TextEntryPointer. That is why there is a copy.
Is there a way to call it on the original element?
Yes. Instead of copy-constructing a TextEntry variable, you could use a reference variable instead:
TextEntry& TextEntry = *TextEntryPointer;
This refers to the object pointed by the element in the vector.
Or more simply, don't create an intermediate variable at all:
int j = TextEntryPointer->ask();
Perhaps not even for the pointer:
int j = (*it)->ask();
You could simplify the loop as well:
for(TextEntry* ptr : d_text) {
int j = ptr->ask();
}
For whatever reason this implementation is giving me an error
There is a missing semicolon
TextEntry TextEntry = *TextEntryPointer // dereference the TextEntry pointer
PS. Avoid naming a variable with a same identifier as a type.
An example program with little bit assumption.
Look into main function for invoking the member function.
#include <iostream>
#include <vector>
using namespace std;
class TextEntry
{
public:
int ask()
{
return 1;
}
};
int main()
{
vector<TextEntry*> te;
TextEntry* te1 = new TextEntry();
TextEntry* te2 = new TextEntry();
TextEntry* te3 = new TextEntry();
TextEntry* te4 = new TextEntry();
te.push_back(te1);
te.push_back(te2);
te.push_back(te3);
te.push_back(te4);
for (std::vector<TextEntry*>::iterator it = te.begin(); it != te.end(); ++it)
{
TextEntry *t = *it;
cout<<t->ask();
}
}
Other answers are correct. But we have 2016 now, so we have c++11:
for (auto& text_entry_ptr: d_text)
{
int j = text_entry_ptr->ask();
}
Much simpler and cleaner.
I have a class that looks like this:
enum DATA_TYPE {bla, bla2};
class Mem_Data
{
private:
DATA_TYPE m_eType;
uint32 m_nLineAddr;
uint32 m_nPhysAddr;
uint32 m_nSize;
int m_nIndex;
public:
Mem_Data(DATA_TYPE eType, uint32 nLineAddr,uint64 nPhysAddr,uint64 m_nSize, int nIndex = 0);
DATA_TYPE GetType();
int GetIndex();
uint32 GetLineAddr();
uint32 GetPhysAddr();
};
I then create a vector that is made from pointers of this class:
Vector<Mem_Data *> m_dataVec;
m_dataVec.push_back(new MemData());
m_dataVec.push_back(new MemData());
m_dataVec.push_back(new MemData());
(Of course I put data to match my constructor but this is just an example)
But when I try to access a function from the class inside the vector Eclipse fails to resolve it.
m_dataVec.front()->GetType()
The above fails to resolve.
However this seems to work:
Mem_Data *p = m_dataVec.front();
p->GetType();
This does resolve but it seems inelegant as it forces me to add another variable and not access the class instance directly.
Would appreciate any suggestions.
vector.begin() returns an iterator.
In order to get access to the data stored in the vector, or more specifically, to the data the iterator points to, you need to dereference the iterator.
you do this with either operator*() or operator->().
In your example, you would do this as follows:
auto iterator = m_dataVec.begin(); // get iterator from vector
Mem_Data *p = *iterator; // dereference iterator to get Mem_Data pointer
You can dereference begin() in one line using *:
*m_dataVec.begin() // this is a Mem_Data pointer
You can then get access to the data the pointer is pointing as using either * or ->:
(*m_dataVec.begin())->GetType();
Note here the parens around (*m_dataVec.begin()) are necessary because of operator precedence.
Another way to do the same is double-dereference, which would give you access to Mem_Data&:
**m_dataVec.begin().GetType(); // double deref - 1st the iterator, then the pointer
This is what I ended up using:
((Mem_Data*)cve.m_dataVec[0])->GetLineAddr()
It seems that the vector implementation kept trying to use the consts [] operator instead of the normal [] operator, and this solved it.
I have a class Normal defined as:
class Normal
{
bool value;
float time;
public:
Normal(bool val,float time): value(val),time(time) {}
}
Also, I have declared a map variable as:
map<string,Normal> myMap;
Now I want to insert an data into this map.
Is this way of inserting correct?
Normal temp(true,45.04);
myMap.insert(pair<string,Normal>("one",temp));
or
myMap["one"]=temp;
How should i insert data into the map?
In C++03 :
myMap.insert(std::make_pair(
"one",
Normal(true, 45.04)
));
In C++11 :
m.emplace(std::piecewise_construct,
std::forward_as_tuple("one"),
std::forward_as_tuple(true, 45.04)
);
Both avoid default-constructing a key-value pair inside operator[] and then overwriting it.
Use this code
Normal *temp = new Normal(true,45.9);
mymap.insert(make_pair("one",temp));
avoid shallow copy since pointer is involved.
EDIT: Use insert function to insert data in map. Index is not the best way. specially when u r accessing
See this link for details
In STL maps, is it better to use map::insert than []?
EDIT2: For deletion,use the below code.
for(std::map<string, Normal*>::iterator itr = mymap.begin();it != mymap.end();)
{
if(it->second != NULL)
{
delete (it->second);
(it->second) = NULL;
it=mymap.erase(it);
}
else
{
++it;
}
}
this is my first time using the list STL and i'm not sure if what i'm trying to do is possible.
I have class_B which holds a list of class_A, I need a function in class_B that takes an ID, searches the list for an instance with the same ID, and gets a pointer form the list to the instance in that list:
bool class_B::get_pointer(int ID,class_A* pointer2A){
list<class_A>::iterator i;
for(i=class_A.begin();i!=class_A.end();i++){
if((*i).get_id()==ID) {
\\pointer2A=(i);<---------------this is what I'm trying to do
return true;
}
}
pointer2A=NULL;
return false;
}
how do I perform this, is it possible to convert from iterator to instance ?
EDIT:
I'm using this function in a multi-threaded program and I can't return an iterator to the calling function since another thread might delete an element of the list.
Now that I have a pointer to my element(and lets say it's locked so it can't be deleted), and a different thread removed another element and performed a sort on the list, what will happen to the pointer I'm holding ? (I don't know how the list rearranges the elements, is done by copying the elements using a copy c'tor, or by another mean?).
Useless answer was the most helpful in my case (BIG thanks), and yes I should use a reference to the pointer since I'm planing to change it.
You should write this:
pointer2A= &*i;
Here *i returns the object whose address you can get by prepending & as : &*i.
Note that i is not same as &*i. See this topic for more general discussion:
Difference between &(*similarObject) and similarObject? Are they not same?
Anyway, I would suggest you to read the pointer itself as:
class_A* class_B::get_pointer(int ID)
{
//I assume the name of the list is objA, not class_A
for(list<class_A>::iterator i=objA.begin();i!=objA.end();i++)
{
if( i->get_id()==ID)
{
return &*i;
}
}
return NULL; //or nullptr in C++11
}
Or, in C++11, you can use std::find_if as:
auto it = std::find_if(objA.begin(),
objA.end(),
[&](class_A const &a){ return a->get_id() == ID;});
classA *ptr = NULL;
if ( it != objA.end())
ptr = &*it; //get the pointer from iterator
Make sure get_id is a const member function.
if(i->get_id()==ID) {
pointer2A=&*i;
return true;
}
iterators are designed to have similar semantics to pointers, so for example you can write i->get_id() just as if you had a pointer to A.
Similarly, *i yields a reference A&, and &*i converts that back into a pointer - it looks a bit clunky (it would be an identity operation if i were really a pointer), but it's idiomatic.
Note that this won't do what you presumably want anyway - the caller's class_A* pointer2A is passed by value, so only get_pointer's copy of the pointer is modified, and the caller won't see that value. Try this:
bool class_B::get_pointer(int ID, class_A *& pointer2A)
{
list<class_A>::iterator i;
for(i=class_A.begin();i!=class_A.end();i++) {
if(i->get_id()==ID) {
pointer2A=&*i;
return true;
}
}
pointer2A=NULL;
return false;
}
Now pointer2A is passed by reference, so the caller's copy gets modified inside your function.
BTW, you can read the parameter declaration class_A * & pointer2A right-to-left, as "pointer2A is a reference to a pointer to class_A".
If you have an iterator, you can get a raw pointer by simply dereferencing the iterator (which gives you a reference), and then taking the address of that (which gives you a pointer). So, in your case:
pointer2A = &*i;
This might seem like an odd, clumsy way to get a pointer, and it is. But you normally don't care about pointers when you are using the collections & iterators from the Std Lib. Iterators are the glue that hold the "STL" together. That's what you should be dealing with, by and large, rather than raw pointers.
The loop you've written above certainly gets the job done that you wish to accomplish, but there are better* ways to accomplish the same goal. (Better is a subjective term.) In particular, the <algorithm> library provides both std::find and std::find_if which do just what they say they do. They find something in a collection. find will find something that is equal to what you're looking for. find_if will find something that matches some criteria that you specify. The latter is the appropriate algorithm to use here, and there are two main ways to use it.
The first, more "traditional" approach is to use a functor:
struct match_id : public std::unary_function<bool, class_A>
{
match_id(int ID) : id_(id) {};
bool operator()(const class_A* rhs) const
{
if( id_ == rhs->get_id() )
return true;
else
return true;
};
/* ... */
list<class_A>::iterator it = std::find_if(objA.begin(), objA.end(), match_id(ID));
This approach works in C++03 or C++11. Some people don't like it because it is rather verbose. I like it, on the other hand, because the actual buisness logic (the find_if call) is quite succinct and more expressive than an explicit loop.
In C++11, you can use a lambda in place of the functor:
unsigned ID = 42;
std::find_if( objA.begin(), objB.end(), [&ID](const class_A& rhs) -> bool { return rhs.get_id() == ID; } };
There's a tradeoff here. On the pro side, you don't have to write 10 or so lines of code for the functor, but on the con side, the lambda syntax is funky and takes a bit of getting used to.
I'm having a problem in my c++ game related with the vector.
I want to know if theres any code that tells me if a vector still exists.
Example (x = a structure that I created):
vector<x*> var;
var.push_back(new x);
var[5]->Pos_X = 10;
And now what i want:
delete var[5];
if(var[5] still exists){
var[5]->Pos_X = 20;
}
What could be the code for var[5] still exists?
Unless you've actually set the pointer to null after deleting it, there's no real way to determine whether that slot in the vector contains a pointer to a live object or not.
So you'd need to:
delete vec[5];
vec[5] = NULL;
Then you could test
if (vec[5] == NULL)
to determine if there was "really" something at that location or not.
There is no code for that, not without extra careful work in your deleting process. If you store smart pointers you can do it like this:
vector<unique_ptr<x>> var;
// assuming you actually do add 6 or more elements to the vector
...
var[5].reset();
if (var[5]) { ... }
You could use var.size() to see if the vector contains a pointer at var[5], but that won't tell you whether the pointer is valid.
You could create a small wrapper class:
template <class T>
class wrapper {
bool valid;
T *data_;
public:
wrapper(T *d): data_(d), valid(true) {}
del() { delete data; valid = false; }
bool isValid() { return valid; }
T *data() { return valid ? data : NULL; }
};
std::vector<wrapper<x> > var;
var[5].del();
if (var[5].valid())
var[5].data()->Pos_X = 20;
Personally, I'd prefer to just ensure that all the pointers are valid all the time though.
calling delete you are deallocating memory pointed by that x*, so you still have pointer to some memory address that do not contain anymore what you excpected.
If you want to remove elements from vector consider using "erase"; then, if you don't want to erase but simply "cancel" the Nth element, structure is yours.. put some bool flag inside your structure.