'Why does std::pair return such a random 'second' value?
The issue is that I want to return a pair containing my key and value {8, 8} for example. Instead I get a rather random pair back {8, 19259321} for example, and I'm not sure why, but I'm guessing I'm trying to do something with references that is causing UB. Below is a reproducible example:
#include <iostream>
template <typename Key, typename Value>
class Tree {
public:
class Node {
public:
Key key;
Value value;
Node(Key k, Value v)
{
key = k;
value = v;
}
};
class iterator {
using pointer_type = Node*;
using reference = std::pair<const Key, Value>&;
pointer_type t_Ptr;
public:
iterator(pointer_type ptr) : t_Ptr(ptr) {}
// For the sake of the minimal reproduciable problem, this is the only operator.
reference operator*() const
{
return (std::pair<const Key, Value>&)(t_Ptr->key, t_Ptr->value);
}
};
private:
size_t treeSize;
Node* root;
};
int main()
{
Tree<int, int>::Node* testNode = new Tree<int, int>::Node(8, 8);
Tree<int, int>::iterator it = Tree<int, int>::iterator(testNode);
std::pair<int, int> myPair = *it;
std::cout << myPair.first << ", " << myPair.second << std::endl;
}
The issue is my dereference operator in the iterator.
I should also mention, that the reason my return statement below looks the way it does, is because it was the only solution I found, where I didn't get any errors. In all the other ways I tried returning a pair, it would give me an error similar to
couldn't convert from the list initializer to pair<const Key, Value>&
return (std::pair<const Key, Value>&)(t_Ptr->key, t_Ptr->value);
Solution 1:[1]
I solved the issue. There was a shadowing issue firstly, which I believe I fixed. And instead of having two variables in my class node 'Key' and 'Value', I made one std::pair variable instead, containig both key and value. Then I could return that pair, instead of trying to create and return a new temporary pair, that would cause UB. Fixed code below.
#include <iostream>
template <typename Key, typename Value>
class Tree {
public:
// I removed the template here, as it was unnecessary.
class Node {
public:
// Changed the two variables to a pair.
std::pair<const Key, Value> pair;
// Therefore constructor had to be changed too
Node(Key k, Value v) : pair(k, v) {}
};
class iterator {
using pointer_type = Node*;
using reference = std::pair<const Key, Value>&;
pointer_type t_Ptr;
public:
iterator(pointer_type ptr) : t_Ptr(ptr) {}
// For the sake of the minimal reproduciable problem, this is the only operator.
reference operator*()
{
// I could now just return the variable 'pair'
return t_Ptr->pair;
}
};
private:
size_t treeSize;
Node* root;
};
int main()
{
Tree<int, int>::Node* testNode = new Tree<int, int>::Node(8, 8);
Tree<int, int>::iterator it = Tree<int, int>::iterator(testNode);
std::pair<int, int> myPair = *it;
std::cout << myPair.first << ", " << myPair.second << std::endl;
return 0;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |