class Way {
private:
std::vector<Node> nodesCollection;
public:
Way();
Way(const Way& orig);
virtual ~Way();
void SetNodesCollection(std::vector<Node> nodesCollection);
std::vector<Node> GetNodesCollection() const;
};
I added vector as a property and I'm accessing that vector from following class and adding items.
Way wayNode;
for (; WayIter!=wayNodes.end(); ++WayIter)
{
const JSONNode& arrayNode = *WayIter;
if (arrayNode.find("ref") != arrayNode.end() )
{
std::string id = arrayNode.find("ref")->as_string();
if(nodesMap.find(id) != nodesMap.end())
{
wayNode.GetNodesCollection().push_back(nodesMap.find(id)->second);
}
}
}
but items are not adding to "nodesCollection". its count is zero. that adding object is not null.
I need some help to sort out this. I'm new to c++.
Thanks in advance.
You need to read about pass by value vs pass by reference. GetNodesCollection is returning a brand new copy of the vector. Then you add your nodes to this new copy, instead of to the original.
Well, maybe it is more return by value vs return by reference. Anyway the point is that you are getting a brand new copy instead of a reference to the original vector.
One way to fix would be to change the return type to a reference (you'd have to make the same change where GetNodesCollection is defined)
std::vector<Node>& GetNodesCollection();
Related
I have a playlist class which contains a vector of song pointers.
class Playlist {
public:
Playlist();
Playlist(string);
vector<Song*> GetSongList() const;
private:
vector<Song*> songs;
string name;
};
The function GetSongList() is as follows:
vector<Song*> Playlist::GetSongList() const {
return songs;
}
In my main method I have a vector of playlist pointers: vector<Playlist*> playlists
I want to remove a song pointer from a specific playlist, but I'm having trouble. This is my current code to remove the indicated song:
Playlist* desiredPlaylist = playlists.at(index);
vector<Song*> temporarySongList = desiredPlaylist->GetSongList();
cout << "Pick a song index number to delete: ";
cin >> index;
temporarySongList.erase(tempSongList.begin() + index);
When I erase the song from the vector and re-output the contents of playlists.at(index).GetSongList() the song is not removed. I think the reason why is that calling GetSongList() does not retrieve the actual song vector, but just returns a copy, so I'm not altering the original vector. How do I directly remove the song from the original?
Use a member function remove_playlist to remove the song from the playlist. std::list (in place of vector) is recommended since frequent delete, move and insert is required within the playlist. Also use smart-pointer to avoid memory leaks like this std::list<std::shared_ptr<Song>>
void Playlist::remove_playlist(int index)
{
if( index < songs.size() )
{
auto v = songs.at(index);
songs.erase(std::remove(songs.begin(), songs.end(), v), songs.end());
}
}
You are right, the problem is caused by returning a copy.
You can either return a pointer
vector<Song*>* Playlist::GetSongList() {
return &songs;
}
or a reference
vector<Song*>& Playlist::GetSongList() {
return songs;
}
to your playlist.
A pointer is preferrable when it may happen, that there is no song list available and you thus sometimes have to return nullptr. So not in your example, because the member playlist is always available.
In most other cases, returning a reference is preferrable. Note that the method is not marked as const, because accesses to the returned vector<Song*>& alter the Playlist instance.
Another technique is to not return the member at all, but instead use a delegate to change the member.
void Playlist::ChangeSongList( const std::function<void(vector<Song*>&)>& fn ) {
fn(songs);
}
This has the benefit that the class which supplies the member can lock the access to the member in a threaded environment and is better informed when the member is changed (e.g. for debugging purposes - ChangeSongList could dump the contents before and after calling fn())
Anyway, returning a copy has often also performance problems and thus is often not preferrable. If you want to return a const member, you should use a const reference instead:
const vector<Song*>& Playlist::GetSongList() const {
return songs;
}
Please note that the answer seccpur gave is the most preferrable option in everyday life - a class should and usually takes care of its members itself, and don't let some outside code handle it. But this answer doesn't describe the difference in returning copies, pointers and references.
Quote
Playlist* desiredPlaylist = playlists.at(index);
vector<Song*> temporarySongList = desiredPlaylist->GetSongList();
cout << "Pick a song index number to delete: ";
cin >> index;
temporarySongList.erase(tempSongList.begin() + index);
You are creating a copy by doing this
vector<Song*> temporarySongList = desiredPlaylist->GetSongList();
So you are erasing from your local copy.
Consider changing
vector<Song*> GetSongList() const { return songs };
to
vector<Song*>& GetSongList() { return songs } ;
I added also void Clear()-method.
https://redstoner.com/forums/threads/840-minimal-class-to-replace-std-vector-in-c-for-arduino
https://forum.arduino.cc/index.php?topic=45626.0
I'm asking about this Vector class.
void push_back(Data const &x) {
if (d_capacity == d_size) resize();
d_data[d_size++] = x;
}; // Adds new value. If needed, allocates more space
How to add "insert"-method to this Vector class (arduino use C++ but not have a standard vector methods)?
Vector<Sensor*> sensors;
I have a another class Sensor and I use vector like this.
push.back(new Sensor (1,1,"Sensor_1",2));
Is it possible to add values one by one to this vector class? And how to do it?
I like to ask also other question.
How can I call delete/call destructor for this Vector "sensors" so all pointers are deleted? Or sensors vector is deleted? I want to clear the data and then add data to it.
If you want to add an item to the end of the vector, use the push_back method you've quoted above. If you want to add an item somewhere else in the vector, you'll need to add your own method which re-sizes if necessary, shifts the elements above the insert location up one place and then copies the new element into the correct slot. Something like this (untested):
void insert_at(size_t idx, Data const &data) {
assert(idx < d_size);
if (d_capacity == d_size) {
resize();
}
for (size_t i = d_size; i > idx; --i) {
d_data[i] = std::move(d_data[i - 1]);
}
d_data[idx] = data;
++d_size;
}
As Nacho points out, you might be better off with a linked list if you're going to do a lot of these insert operations, especially if the data you're storing is large and/or has a complex move operator.
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.
I have another problem I can't seem to solve..., or find on this site...
I have an object (called DataObject) with a map, declared as follows:
std::map<size_t, DataElement*> dataElements;
Now i have a copy function (used in the copy constructor):
void DataObject::copy(DataObject const &other) {
//here some code to clean up the old data in this object...
//copy all the elements:
size = other.getSize();
for(size_t i = 0; i < size; ++i) {
DataElement* dat = new DataElement(*other.dataElements[i]);
dataElements[i] = dat;
}
}
This doesn't compile, since dataElements[i] is not possible on a const object. How do I make a deep copy of all the elements in the map that is owned by a const object?
I know that the find() function is possible on a const map, but then how do I get to the actual object that I want to copy?
std::map<size_t, DataElement*>::const_iterator it = other.dataElements.begin();
while(it != other.dataElements.end())
{
dataElements[it->first] = new DataElement(*(it->second));
++it;
}
I'm almost positive this should work.
You need to use std::transform. This does a copy whilst also performing a function on each element. In your case a deep copy of the value.
This will therefore do as a transformer:
class DeepCopyMapPointer
{
typedef std::map<size_t, DataElement*> map_type;
typedef map_type::value_type value_type;
public:
value_type operator()( const value_type & other ) const
{
return value_type(other.first, new DataElement(*other.second) );
}
};
void DataObject::copy(DataObject const &other)
{
std::transform(other.dataElements.begin(), other.dataElements.end(),
std::inserter( dataElements, dataElements.end() ), DeepCopyMapPointer() );
}
It's not quite that simple because if you do duplicate an element and your insert fails as a result you will get a leak. You could get round that by writing your own inserter instead of std::inserter... a bit tricky but that's your next exercise.
Since your map just has integer keys from 0 to n - 1, just change your container type to a vector, and your current code should work nicely (you'll need to resize the destination container to make sure there's enough room available).
If you need to use map for some reason (existing API?), as you discovered operator[] has only a non-const version.
Instead use a const_iterator approach (upvoted and taken from #PigBen's answer):
std::map<size_t, DataElement*>::const_iterator it = other.dataElements.begin();
while(it != other.dataElements.end())
{
dataElements[it->first] = new DataElement(*(it->second));
++it;
}
Don't have much time to answer now so this will be brief. There is a copy-constructor for map, but it won't do a deep copy. You want to use iterators (map.begin(), map.end()). *Iter will give you a pair object, so you can do (*iter).first and/or (*iter).second. (Or something like that... It's been a while...)
Ref: http://www.sgi.com/tech/stl/Map.html
for (auto& kv : other.dataElements) {
dataElements[kv.first] = new DataElement(*kv.second);
}
Just one observation :- You are giving direct access to the dataElements. (other.dataElements). Keep dataElements private and then give method like GetDataElement.
My brain has never really quite grasped linked lists and the finer points of pointers but I'm trying to help out a friend with some C++ assignments. (And before I go any further, yes, there is std::list but I'm looking for an academic answer, and maybe something that will make linked lists more understandable to he and myself).
What we need to do is generate a linked list of objects (a Employee object) based on user input, and then display that information back to the user. Whenever I try to assign the object into the Linked List Container, it segfaults.
I have the following Linked List object:
class LinkedListContainer {
private:
Employee *emp;
LinkedListContainer *next;
public:
Employee getEmployee() { return *emp; }
void setEmployee(Employee *newEmp) {
*emp = *newEmp // This is what is causing the segfault
}
LinkedListContainer getNext() { return *next; }
void setNext(LinkedListContainer *newContainer) {
*next = *newContainer;
}
}
I'm sure that I'm doing something horribly wrong.
Looking at your class, there doesn't appear to be a place where the pointer emp is set to point at an actual object.
This line:
*emp = *newEmp;
assigns the value of the object pointed to by newEmp to the object pointed to by emp. Unless both pointers point at valid objects, the code will have undefined behaviour.
You may be better having emp as an Employee object rather than as a pointer to an object requiring manually management of the pointed to object's lifetime.
This assumes that your LinkedListContainer class is a node which will own the Employee.
On the other hand when you do:
*next = *newContainer;
from the naming I would assume that you just want to point the next pointer at another LinkedListContainer for which you would probably want to do:
next = newContainer;
as this assigns the value of the pointer to the variable next.
You need to be clear when you design your class and use pointers, on which objects own which other objects and ensure that you manage their lifetimes appropriately.
*emp = *newEmp;
Should be:
emp = newEmp;
So that you're assigning the pointer and not the object pointed to by the pointer.
Your emp pointer is uninitialized, so when you attempt to dereference it (*emp) in setEmployee() you attempt to access memory that doesn't belong to you (hence the segfault).
You might be better off holding the Employee by value (assuming it's not polymorphic) and passing the setEmployee an Employee object by const reference:
class LinkedListContainer {
Employee emp;
// ...
void setEmployee(const Employee& newEmp) {
emp = newEmp;
}
// ...
};
Of course, you'll need to adjust your other member functions as well to reflect using a value vs. a pointer.
Good luck!
*emp = *newEmp
You don't want to do this - in fact, you don't want to dereference any pointers at all here.
emp = newEmp
By default, emp is a pointer that's pointing nowhere. By writing
*emp = *newEmp;
you try to assign the content of newEmp to whatever memory location is pointed to by emp. As said, emp is pointing nowhere, so you are dereferencing a NULL pointer here, which is causing the segmentation fault.
If your container is to contain a complete Employee, you'd better declare emp to be of type Employee (not pointer to Employee as now). Then
emp = *newEmp;
will work, although I'm not quite sure whether this will be all you'd need to fix about your LinkedListContainer.
One of the issues that you are having is because of the leading * when you access the pointer. What * tells the compiler when accessing a pointer is that instead of reading the address the pointer points to it should read the value of the location that the pointer points to.
An example is variables are like houses that hold values. A pointer is like the address on the house. Typically when the compiler reads a pointer it only sees the address. When you put * infront of the pointer it tells the compiler to look inside the "house" to extract the value within. When you assign pointers new addresses you do not want to use the * or else you are copying values and not the addresses.
So what you want to be doing instead is in the setNext for example:
next = newContainer;
Previous answers explain reason of segmentation fault. Anyway if you need that sample for academic use, then IMHO you forgot about initialization of class members. The second issue is memory management - who does alloc/free these objects? In your sample there is nor constructor, neither destructor :)
Your class could look like this one below:
class LinkedListContainer
{
public:
LinkedListContainer()
: d_emp( 0 )
, d_next( 0 )
{
}
bool isValid() const
{
const bool result = ( d_emp != 0 );
return result;
}
const Employee& getEmployee() const
{
assert( isValid() );
return *d_emp;
}
void setEmployee( Employee* emp )
{
d_emp = emp;
}
LinkedListContainer* getNext()
{
return d_next;
}
void setNext( LinkedListContainer* next )
{
d_next = next;
}
private:
Employee* d_emp;
LinkedListContainer* d_next;
};
If you don't want to bother with memory management for Employee objects, then just use shared_ptr from boost library.
typedef boost::shared_ptr< Employee > SmartEmployee;
class LinkedListContainer
{
public:
LinkedListContainer()
: d_next( 0 )
{
}
bool isValid() const
{
return d_emp;
}
const Employee& getEmployee() const
{
assert( isValid() );
return *d_emp;
}
void setEmployee( SmartEmployee emp )
{
d_emp = emp;
}
LinkedListContainer* getNext()
{
return d_next;
}
void setNext( LinkedListContainer* next )
{
d_next = next;
}
private:
SmartEmployee d_emp;
LinkedListContainer* d_next;
};