Rafael K. Rafael K. - 6 days ago 5
C++ Question

C++ "=" operator behavior for a class with a private vector and iterator for it

I'm trying to make an object that gives sequentially an output but I don't want to expose the inner implementation. I want the other classes to see just the methods hasNextOutput() and nextOutput(). Here is my header file and class file respectively:

header file:

#ifndef RADAR_OUTPUT_GENERATOR_H
#define RADAR_OUTPUT_GENERATOR_H

#include<vector>
#include<iterator>
#include "asl/include/net/asl_net_user_data.h"

class RadarOutputGenerator {
private:
int dataCounter;
std::vector<unsigned char *> dataStream;
std::vector<unsigned char *>::iterator dataStreamIterator;
public:
RadarOutputGenerator();
RadarOutputGenerator(char *filename);
RadarOutputGenerator(unsigned int maxDataSize);
~RadarOutputGenerator();

bool hasNextOutput();
void nextOutput(unsigned char *&dataWithHeader);
};

#endif


The class implementation

#include "radar_output_generator.h";

RadarOutputGenerator::RadarOutputGenerator() {

}

RadarOutputGenerator::RadarOutputGenerator(unsigned int maxDataSize) {
for (int i = 0; i < 100; i++) {
// create some data

this->dataStream.push_back(data);

cur_step = (cur_step += 10) & 65535;
}

this->dataStreamIterator = (this->dataStream).begin();
}

bool RadarOutputGenerator::hasNextOutput() {
return (this->dataStreamIterator != this->dataStream.end());
}

void RadarOutputGenerator::nextOutput(unsigned char *&dataWithHeader) {
dataWithHeader = *(this->dataStreamIterator++);
}


The problem is that when I construct an object of type RadarOutputGenerator, the hasNext() method fails on "iterators incompatible" error, e.g. this code fails:

RadarOutputGenerator myOutputGenerator = RadarOutputGenerator(47);
radarOutputGenerator.hasNextOutput(); // this line fails


I think I see where is the problem - probably when invoking the "=" operator the vector dataStream is copied and the iterator initialized in the constructor keeps the reference to the original vector. If that's the case, this behaviour kind of dissapoints me but I'd like to know, how to fix this problem properly.

Answer

One way to solve this is to overload the copy constructor and copy assignment operator to do the right thing, i.e. compute the offset of the iterator into the old vector, and create a new iterator that points that far into the new vector.

As a general rule, whenever an object has an interior pointer (something that refers to a part of itself), you will need to implement copying manually.

A simpler solution, but not as universally applicable, is to do as n.m. said in the comments and store an index instead of an iterator. An index is not associated with a particular vector.

Comments