Dereferencing iterator (c++) - c++

I have problem with dereferencing result of operation that returns non-pointer value.
In this map i have pointers to matrixes
map<string, GeneralMatrix*> matrixes;
and this is how operations with matrixes look like
GeneralMatrix & add(const GeneralMatrix & m2) {
//Check for compatible matrixes
if (height != m2.height || width != m2.width) {
cout << "Matrix sizes must match!" << endl;
return *this;
}
//Create new empty matrix
GeneralMatrix &m3 = createNew(width, m2.height);
//Set every number to sum of this and given matrix
for (int i = 0; i < height; i++) {
for (int j = 0; j < m2.width; j++) {
double val = m2.get(i, j);
if (val != 0) {
val += get(i, j);
m3.set(i, j, val);
}
}
}
return m3;
}
As you can see, add method returns non-pointer matrix that i want to insert into my map.
This is what I tried:
map<string, GeneralMatrix *>::iterator itop1 , itop2;
//now seting iterators to their position
//there is the problem
matrixes.insert(pair<string, GeneralMatrix *>(result, (*itop1->second->add(*itop2->second))));
Problem is that i cant find out how to insert second parameter of pair. It alway ends with error because of different types.
Attempt n1:
itop1->second->add(itop2->second)
Add method needs pointer
Attempt n2:
itop1->second->add(*itop2->second)
Result is non-pointer, needs to be pointer
Attemp n3:
(*itop1->second->add(*itop2->second))
main.cpp:611:68: error: no match for ‘operator*’ (operand type is ‘GeneralMatrix’)
How to derefence result then ?

Ideally you would change matrixes to type map<string, GeneralMatrix>.
Alternatively you could keep an std::list<GeneralMatrix> that stores the matrices and you give a pointer to the matrix inside the list.
It is considered bad style to have naked pointers. Pointers should instead tell the ownership status they have over the item, such as unique_ptr, shared_ptr or weak_ptr. That would also take care of memory management.
If your class is well behaved and the map holds owning pointers you could do something like this:
matrixes.insert(std::make_pair(std::string("name"), new GeneralMatrix(std::move(m)));
Where m is the matrix you are trying to move into the map.
If the pointers in the map do not own the pointers you can just insert the address of the map with &m, but that requires you to store the matrix somewhere persistent such as the list shown above.
Edit:
Your specific problem with the iterator can be solved like this:
matrixes.insert(pair<string, GeneralMatrix *>(result, &(*itop1)));

A quick solution to your problem is:
GeneralMatrix& m3= add(m2);
matrixes["string"] = &m3;
matrixes.insert(std::make_pair(std::string("name"), (&m3)));
matrixes.insert(std::make_pair<std::string, GeneralMatrix*>("name", &m3));
They are basically both equivalent in this case, however operator[] will always insert a value in the map, even if the right hand operator is null.
For example:
matrixes["s"];
will insert an empty pointer
Your code however has several problems:
first, why do you need to return a reference from the method createNew?
Just return a value to a new matrix. You don't gain anything doing this.
GeneralMatrix createNew(width, m2.height);
As suggested in another answer, have a map of string to unique_pointers instead of using raw pointers and/or leverage move semantics.
In your case, since an "add" operation will always result in creating a new matrix, I wouldn't even bother dealing with pointers, as they give you no real advantage
Here you can find some stripped down code that will fit your needs:
std::map<std::string, GeneralMatrix> matrixes;
GeneralMatrix add(const GeneralMatrix& m2)
{
//Create new empty matrix
auto m3 = createNew(width, m2.height);
return m3;
}
Note also that this code will be optimized by your compiled, using something called NRVO (named return valueoptimization), and it will likely be faster that your previous one that dealt with dynamic allocation in the createNew method).
Now, if General matrix implements correctly the rvalue copy constructor you can move it to your map
map.insert(std::string("string"), std::move<m3>);
or you can just emplace it (not yet implemented by all compilers)
map.emplace(std::make_pair(std::string("string"), createNew(m2)));
If you need polymorphism, just use a factory method that returns a base std::unique_ptr.
std::unique_ptr<GeneralMatrix> createNew(width, m2.height);

Related

Sorting a C 2D array via std::sort

I have a 2D array a[][40]. I'm trying to sort it by calling std::sort, and I have written the Compare function. However, C++ wants me to have a std::vector to be sorted, not a simple array and I want the sorted array to be a itself, I don't want to create another array and save the sorting result there. It seems there are a lot of ways to achieve that. I could think of five ways, but none of them seems to be efficient and working.
1)
Directly use std::sort(std::begin(a), std::begin(a) + something, cmp);
It doesn't work, because std::begin doesn't know how to point to the beginning of a 2D array. Furthermore, it'd sort incorrectly even if it compiled, since a 2D array is not an array of references to arrays, but consecutive arrays (unlike Java)
Playground: https://godbolt.org/g/1tu3TF
2)
std::vector<unsigned char[40]> k(a, a + x);
std::sort(k.begin(), k.end(), cmp);
Then copy everything back to a
It doesn't work, because it's a 2D array, and it can't be sorted this way, using std::sort. In contrast to the first trial, this one uses twice as much as memory, and copies everything twice (if it worked)!
Playground: https://godbolt.org/g/TgCT6Z
3)
std::vector<int> k(x);
for (int i = 0; i < x; k[i] = i, i++);
std::sort(k.begin(), k.end(), cmp2);
Then change the order of a to be the same of k;
The idea is simple, create a vector of representative "pointers", sort them (as the cmp2 function secretly accesses a and compares the values), then make a have the same order with k.
In the end, the re-ordering loop will be very complex, will require a large, temporary variable. Besides, for cmp2 to access the values of a, a global variable-pointer that points to a must be created, which is "bad" code.
Playground: https://godbolt.org/g/EjdMo7
4)
For all unsigned char[40], a struct can be created and their values can be copied to structs. Comparison and = operators will need to be declared. After sorted, they can be copied back to a.
It'd be a great solution if the arrays didn't have to be copied to structs to use struct's operators, but they need to be copied, so all values will be copied twice, and twice-as-needed memory will be used.
5)
For all unsigned char[40], a struct that has a pointer to them can be created. They can be sorted by the pointed values, and the result can be saved to a pointer array.
It's probably the best option, although the result is a pointer array instead a. Another reason on why it's good is it doesn't move the arrays, but the pointers.
To sum up, I need to sort the 2D array a[][40] via std::sort, but I haven't decided on the best way. It seems there's a "best way to do that" which I can't think of. Could you please help me?
EDIT: To clarify, I want {{3,2}{1,4}} to become {{1,4}{3,2}}
The problem is not in iterating a 2D array. Provided the columns size is a constexpr value, pointers to arrays are nice iterators.
But all C++ sort (or mutating) algorithms require the underlying type to be move constructible and move assignable and an array is not assignable. But wrapping the underlying arrays can be enough:
template <class T, int sz>
class wrapper {
T* base;
bool own; // a trick to allow temporaries: only them have own == true
public:
// constructor using a existing array
wrapper(T* arr): base(arr), own(false) {}
~wrapper() { // destructor
if (own) {
delete[] base; // destruct array for a temporary wrapper
}
}
// move constructor - in fact copy to a temporary array
wrapper(wrapper<T, sz>&& src): base(new T[sz]), own(true) {
for(int i=0; i<sz; i++) {
base[i] = src.base[i];
}
}
// move assignment operator - in fact also copy
wrapper<T, sz>& operator = (wrapper<T, sz>&& src) {
for(int i=0; i<sz; i++) {
base[i] = src.base[i];
}
return *this;
}
// native ordering based on lexicographic string order
bool operator < (const wrapper<T, sz>& other) const {
return std::char_traits<char>::compare(base, other.base, sz) < 0;
}
const T* value() const { // access to the underlying string for tests
return base;
}
};
Then, you can sort a C compatible 2D array with any C++ sort algo:
std::vector<wrapper<char, 40> > v { &arr[0], &arr[sz] }; // pointer are iterators...
std::sort(v.begin(), v.end()); // and that's all!
for (int i=0; i<sz; i++) { // control
std::cout << arr[i] << std::endl;
}
The overhead is a vector of structures containing a pointer and a bool, but what is sorted is actually the original 2D array.
Of course, as the C library is accessible from C++, qsort would certainly be easier for sorting a C compatible 2D array. But this way allows the use of stable_sort or partial_sort if they are relevant.

Moving from old C-style pointer to C++ smart pointers with little changes in the code?

I have a function in which the nodes of a binary 'tree' are populated with values recursively computed based on the input vector, which represents the values on the leaves. An old C++ implementation of the function is as follows
using namespace std;
double f(const size_t h, vector<double>& input) {
double** x;
x = new double*[h+1];
x[0] = input.data();
for (size_t l = 1; l <= h; l++)
x[l] = new double[1<<(h-l)];
// do the computations on the tree where x[l][n] is the value
// on the node n at level l.
result = x[l][0];
for (size_t l = 1; l <= h; l++)
delete[] x[l];
delete[] x;
return result;
}
Now I'm trying to write a 'modern' implementation of the code using smart pointers in C++11/C++14. I attempted to define x using std::unique_ptr specialization for arrays so that I do not have to change the 'computation' procedure. The obvious problem with such an approach is that the contents of `input' will be deleted at the end of the function (because the unique pointer that takes the ownership of the data will be destroyed at the end of the function).
One simple (and perhaps safe) solution would be to allocate the memory for the whole tree (including the leaves) in x and copy the values of the leaves from input to x[0] in the beginning of the function (in this case I can even used nested std::vectors instead of std::unique_ptrs specialized for arrays as the type of x). But I prefer to avoid the cost of copying.
Alternatively one can change the computational procedures to read the values of the leaves directly from input not from x which requires changing too many small pieces of the code.
Is there any other way to do this?
C++11/14 didn't really introduce anything that wasn't already achievable prior using the modern std::vector for managing the memory of dynamic arrays.
The obvious problem with [std::unique_ptr] is that the contents of `input' will be deleted at the end of the function
Indeed. You may not "steal" the buffer of the input vector (except into another vector, by swapping or moving). This would lead to undefined behaviour.
Alternatively one can change the computational procedures to read the values of the leaves directly from input not from x which requires changing too many small pieces of the code.
This alternative makes a lot of sense. It is unclear why the input vector must be pointed by x[0]. The loops start from 1, so it appears to not be used by them. If it is only ever referenced directly, then it would make much more sense to use the input argument itself. With the shown code, I expect that this would simplify your function greatly.
Also the fact that the input is not taken as const std::vector& bothers me.
This is another reason to not point to the input vector from the modifiable x[0]. The limitation can however be worked around using const_cast. This is the kind of situation what const_cast is for.
Let us assume henceforth that it makes sense for the input to be part of the local array of arrays.
One simple (and perhaps safe) solution would be to allocate the memory for the whole tree (including the leaves) in x ... I can even used nested std::vectors ... But I prefer to avoid the cost of copying.
You don't necessarily need to copy if you use a vector of vectors. You can swap or move the input vector into x[0]. Once the processing is complete, you can restore the input if so desired by swapping or moving back. None of this is necessary if you keep the input separate as suggested.
I suggest another approach. The following suggestion is primarily a performance optimization, since it reduces the number of allocations to 2. As a bonus, it just so happens to also easily fit with your desire to point to input vector from the local array of arrays. The idea is to allocate all of the tree in one flat vector, and allocate another vector for bare pointers into the content vector.
Here is an example that uses the input vector as x[0], but it is easy to change if you choose to use input directly.
double f(const size_t h, const std::vector<double>& input) {
std::vector<double*> x(h + 1);
x[0] = const_cast<double*>(input.data()); // take extra care not to modify x[0]
// (1 << 0) + (1 << 1) + ... + (1 << (h-1)) == (1 << h) - 1
std::vector<double> tree((1 << h) - 1);
for (std::size_t index = 0, l = 1; l <= h; l++) {
x[l] = &tree[index];
index += (1 << (h - l));
}
// do the computations on the tree where x[l][n] is the value
// on the node n at level l.
return x[l][0];
}
This certainly looks like a job for a std::vector<std::vector<double>>, not std::unique_ptr, but with the additional complexity that you conceptually want the vector to own only a part of its contents, while the first element is a non-owned reference to the input vector (and not a copy).
That's not directly possible, but you can add an additional layer of indirection to achieve the desired effect. If I understand your problem correctly, you want to behave x such that it supports an operator[] where an argument of 0 refers to input, whereas arguments > 0 refer to data owned by x itself.
I'd write a simple container implemented in terms of std::vector for that. Here is a toy example; I've called the container SpecialVector:
#include <vector>
double f(const std::size_t h, std::vector<double>& input) {
struct SpecialVector {
SpecialVector(std::vector<double>& input) :
owned(),
input(input)
{}
std::vector<std::vector<double>> owned;
std::vector<double>& input;
std::vector<double>& operator[](int index) {
if (index == 0) {
return input;
} else {
return owned[index - 1];
}
}
void add(int size) {
owned.emplace_back(size);
}
};
SpecialVector x(input);
for (std::size_t l = 1; l <= h; l++)
x.add(1<<(h-l));
// do the computations on the tree where x[l][n] is the value
// on the node n at level l.
auto result = x[1][0];
return result;
}
int main() {
std::vector<double> input { 1.0, 2.0, 3.0 };
f(10, input);
}
This approach allows the rest of the legacy code to continue to use [] exactly as it did before.
Write a class Row, which contains a flag for ownership controlling destruction behavior and implement operator[], then create a vector of row.
As noted above, you have issues if input is constant, as you cannot explicitly enforce it at compiler level, and you have to be careful not to write where you cannot, but this is not worse then what you have now.
I have not tried to compile it, but your new Row class could look a bit like this.
class Row
{
double *p;
bool f;
public:
Row() :p(0), f(false) {}
void init(size_t n) { p = new double[n]; f=true; }
void init(double *d) { p=d;, f=false;}
double operator[](size_t i) { return p[i]; }
~Row() { if (flag) delete[] p; }
};

C++ Most efficient way iterate specific contents in vector

I have two vectors, vec and p, such that p is a vector of pointers to different locations in vec.
So something like:
p[0] = &vec[12]
p[1] = &vec[20]
p[3] = &vec[1]
etc.
p's size will always be less than or equal to vec, and will contain no duplicate references to the same location in vec.
What I'd like to have is some data structure that I can iterate through to get the dereferenced values of p in the order of the index they are pointing to in a. So for the above example, the result would need to iterate through in the order vec[1], vec[12], vec[20].
I know can get the position in vec the p is pointing to be doing something like p[i] - &vec[0], and could probably implement this using std::sort and a custom comparing function, but I feel like there is a more efficient way to do this than the O(nlogn) of the sort function. I could also be completely wrong about that.
Thanks for any help!
After discarding a few mental ideas, I thought of a simple one:
std::vector<char> is_pointed_to(vec.size(), 0);//initialize the "bools" to "false"
//set is_pointed_to values
for(T* pointer : p) {
size_t orig_index = pointer - &vec[0];
is_pointed_to[orig_index] = 1; //set this index to "true"
}
//now do the iteration
for(int i=0; i<vec.size(); ++i) {
if(is_pointed_to[i]) {
//DO TASK HERE
}
}
This is clearly a two-pass algorithm, so O(n). Easy.
StilesCrisis reminds me that this is an implementation of the counting sort.

Access violation reading - vector of string pointers to value in vector of strings

I'm not very experienced programmer in C++ and I have a problem which I can't resolve. The project on which I'm working is quite big so I can't post here all codes. It is too much code and too much explanation. I write just little part of code, the part which causes me problem, so I hope it is enough. Sorry for the long of my question but I want explain all posted code. Maybe this part of code isn't enough to solve the problem but I want to try it.
First I have a struct called "record":
struct record {
vector<string> dataRow;
vector<string *> keys;
vector<string *> values;
void setDataRow(vector<string> r) {
dataRow = r;
}
}
Some of string data are marked as keys and others as values. I next processing is better for me to have all string data in one vector, so that's the reason why I don't have two vectors of string (vector keys, vector values).
Then I have this:
vector< vector<record> > resultSet;
vector is like data table - set of lines with string data. I need specific count of these tables, therefore vector of vectors of records. The count of tables is optional, so when I set table count I prepare tables by reserve function:
resultSet.reserve(count);
for(unsigned int i = 0; i < count; i++) {
vector<record> vec;
resultSet.push_back(vec);
}
When I want add new record to resultSet I know the number of table to which I need insert record. After resultSet[number].push_back(rec) I need change pointers in vectors "keys" and "values" because push_back() creates new copy of "rec" with values of "dataRow" in other memory addresses, right? So I have this function which does push_back and updates pointers:
void insert(int part, vector<string> & dataRow) {
record r;
r.setDataRow(dataRow);
resultSet[part].push_back(r);
int pos = resultSet.size() - 1; // position of last record
resultSet[part].at(pos).values.clear();
resultSet[part].at(pos).keys.clear();
for(unsigned int i = 0; i < dataRow.size(); i++) {
record * newRec = &resultSet[part].at(pos);
if(isValue(dataRow[i])) {
newRec->values.push_back(&(newRec->dataRow.at(i)));
// control cout...
} else {
newRec->keys.push_back(&(newRec->dataRow.at(i)));
// control cout...
}
}
}
This is working. After push_back in newRec I did control cout of inserted pointers and their referenced values, and everything was ok.
But! After some inserts I call function processData(resultSet), which has to process all data in resultSet. Before implementing processing od data I just wanted print all keys for control to find out if everything is alright. This code:
for(unsigned int i = 0; i < resultSet.size(); i++) {
for(unsigned int j = 0; j < resultSet[i].size(); j++) {
cout << "keys: ";
for(unsigned int k = 0; k < resultSet[i].at(j).keys.size(); k++) {
cout << *resultSet[i].at(j).keys.at(k) << ", ";
}
cout << endl;
}
}
is bad (Same problem with printing values vector of record). It throws exception of Access violation reading. I know that this exception is thrown when I want to read unaccessible memory, right? Please, tell me that I have mistake in code written above because I really don't know why it doesn't work. Before processing resultSet I do nothing with resultSet except some count of inserts.
Thank you for reading and possible answers.
When you add an entry to a std::vector, all existing pointers to elements in that vector should be considered invalid.
Here is the code that is going wrong.
vector<string> dataRow;
vector<string *> keys;
vector<string *> values;
If keys and values point to the strings in dataRow they will become invalid when dataRow grows.
If I have understood your question correctly, the reason for all this is a fundamental misconception in the way vectors behave.
Your code stores pointers in a vector that points to memory locations allocated by another vector. That would be fine if the vectors didn't change.
The reason for this is that a std::vector is a container that makes a guarantee - all the data it contains will be allocated in a contiguous block of memory.
Now, if you insert an element into a vector, it may move memory locations around. Hence, one of the things you should know is that iterators need to be considered invalid when a vector changes. Iterators are sort of a generalized pointer. In other words, pointers to the locations of elements inside a vector become invalid too.
Now, let's say you updated all your pointers, everywhere, when any of the vectors involved changed. You would then be fine. However, you've now got a bit of an uphill battle on your hands.
As you've said in your comments, you're using pointers because you want efficiency. Your struct is essentially a collection of three strings. Instead of using your own struct, typedef a std::tuple (you will need a C++11 compiler) of 3 std::strings.
Finally, when you need to access the data within, do so by const reference and const_iterator unless you need to modify any of it. This will ensure that
You don't have duplication of data
You're making maximum use of the STL, thereby minimizing your own code and the possible bugs
You're relying on algorithms and containers that are already really efficient
You're using the STL in a way it was meant to be used.
Hope this helps.
One possible problem could be in copies of record instances.
struct record
{
vector<string> dataRow;
vector<string *> keys;
vector<string *> values;
};
In fact, default copy constructor and copy operator= do a member-wise copy. This is OK for dataRow field (which is a vector<string>), but this is bad for keys and values fields (since these are vectors of raw pointers, their values are copied, but they point to something wrong).
I'd reconsider your design, e.g. using vector<int> instead of vector<string *> for keys and values fields. The ints stored would be indexes in the dataRow vector.
Another note (not directly related to your problem).
In C++11, when you want to copy something, you may want to pass by value, and move from the value:
void setDataRow(vector<string> r)
{
dataRow = std::move(r);
}
Or just use old C++98/03 style of passing by const ref:
void setDataRow(const vector<string>& r)
{
dataRow = r;
}

Deleting an element from an array of pointers

I'm creating a custom vector class as part of a homework assignment. What I am currently trying to do is implement a function called erase, which will take an integer as an argument, decrease my array length by 1, remove the element at the position specified by the argument, and finally shift all the elements down to fill in the gap left by "erased" element.
What I am not completely understanding, due to my lack of experience with this language, is how you can delete a single element from an array of pointers.
Currently, I have the following implemented:
void myvector::erase(int i)
{
if(i != max_size)
{
for(int x = i; x < max_size; x++)
{
vec_array[x] = vec_array[x+1];
}
vec_size --;
//delete element from vector;
}
else
//delete element from vector
}
The class declaration and constructors look like this:
template <typename T>
class myvector
{
private:
T *vec_array;
int vec_size;
int max_size;
bool is_empty;
public:
myvector::myvector(int max_size_input)
{
max_size = max_size_input;
vec_array = new T[max_size];
vec_size = 0;
}
I have tried the following:
Using delete to try and delete an element
delete vec_size[max_size];
vec_size[max_size] = NULL;
Setting the value of the element to NULL or 0
vec_size[max_size] = NULL
or
vec_size[max_size] = 0
None of which are working for me due to either operator "=" being ambiguous or specified type not being able to be cast to void *.
I'm probably missing something simple, but I just can't seem to get passed this. Any help would be much appreciated. Again, sorry for the lack of experience if this is something silly.
If your custom vector class is supposed to work like std::vector, then don't concern yourself with object destruction. If you need to erase an element, you simply copy all elements following it by one position to the left:
void myvector::erase(int i)
{
for (int x = i + 1; x < vec_size; x++) {
vec_array[x - 1] = vec_array[x];
}
vec_size--;
}
That's all the basic work your erase() function has to do.
If the elements happen to be pointers, you shouldn't care; the user of your vector class is responsible for deleting those pointers if that's needed. You cannot determine if they can actually be deleted (the pointers might point to automatic stack variables, which are not deletable.)
So, do not ever call delete on an element of your vector.
If your vector class has a clear() function, and you want to make sure the elements are destructed, simply:
delete[] vec_array;
vec_array = new T[max_size];
vec_size = 0;
And this is how std::vector works, actually. (Well, the basic logic of it; of course you can optimize a hell of a lot of stuff in a vector implementation.)
Since this is homework i wont give you a definitive solution, but here is one method of erasing a value:
loop through and find value specified in erase function
mark values position in the array
starting from that position, move all elements values to the previous element(overlapping 'erased' value)
for i starting at position, i less than size minus one, i plus plus
element equals next element
reduce size of vector by 1
see if this is a big enough hint.