Decrease operation in fibonacci heap, boost - c++

I'm trying to use in my implementation the fibonacci heap from boost but my program crashes, when I calling decrease function, this the example (W is a simple class):
struct heap_data
{
boost::heap::fibonacci_heap<heap_data>::handle_type handle;
W* payload;
heap_data(W* w)
{
payload = w;
}
bool operator<(heap_data const & rhs) const
{
return payload->get_key() < rhs.payload->get_key();
}
};
int main()
{
boost::heap::fibonacci_heap<heap_data> heap;
vector<heap_data> A;
for (int i = 0; i < 10; i++)
{
W* w = new W(i, i + 3);
heap_data f(w);
A.push_back(f);
boost::heap::fibonacci_heap<heap_data>::handle_type handle = heap.push(f);
(*handle).handle = handle; // store handle in node
}
A[5].payload->decr();
heap.decrease(A[5].handle);
return 0;
}

The problem is quite trivial.
You have two containers (vector A and heap heap).
The heap contains copies of the data in the vector:
A.push_back(f); // copies f!
handle_type handle = heap.push(f); // copies f again!
You set the handle only on the copy in the heap:
(*handle).handle = handle; // store handle in the heap node only
Hence, in the temporary f and the vector A's elements, the value of handle is indeterminate (you just didn't give it any value).
Therefore when you do
heap.decrease(A[5].handle);
you invoke Undefined Behaviour because you depend on the value of A[5].handle, which is uninitialized.
Simpler, correct, example:
Live On Coliru
#include <boost/heap/fibonacci_heap.hpp>
#include <boost/tuple/tuple_comparison.hpp>
struct W {
int a;
int b;
W(int a, int b) : a(a), b(b) { }
boost::tuple<int const&, int const&> get_key() const { return boost::tie(a, b); }
void decr() { b?a:--a, b?--b:b; }
};
struct heap_data;
using Heap = boost::heap::fibonacci_heap<heap_data>;
struct heap_data
{
W payload;
Heap::handle_type handle;
heap_data(W w) : payload(w), handle() {}
bool operator<(heap_data const & rhs) const {
return payload.get_key() < rhs.payload.get_key();
}
};
#include <vector>
#include <iostream>
int main()
{
Heap heap;
std::vector<Heap::handle_type> handles;
for (int i = 0; i < 10; i++)
{
Heap::handle_type h = heap.push(W { i, i + 3 });
handles.push_back(h);
(*h).handle = h;
}
(*handles[5]).payload.decr();
heap.decrease(handles[5]);
}

Related

Assignment and retrieval using subscript and equals operator overloads

I've been having a hell of a time trying to solve this. What I am trying to do is use operator overloading so that my objects behave more like a multi dimensional array. I've found solutions to several of the smaller problems involved in making this happen but whenever I try to put it all together there is one issue or another, either lvalue assignment error or invalid initialization from rvalue or just straight up seg fault. I would appreciate any advice TY.
#include <iostream>
#include <vector>
#include <string>
class Matrix {
std::string **m;
public:
Matrix(int x, int y) {
m = new std::string*[x];
for (int i = 0; i < x; i++)
m[x] = new std::string[y];
}
class Proxy {
std::string *mm;
int lastIndex = 0;
public:
Proxy(std::string *s) : mm(s) {}
std::string &operator[](int index) {
lastIndex = index;
return mm[index];
}
std::string &operator=(std::string s) {
mm[lastIndex] = s;
return mm[lastIndex];
}
};
Proxy operator[](int index) {
return Proxy(m[index]);
}
};
int main()
{
Matrix *m = new Matrix(5, 5);
m[2][2] = std::string("It Works");
std::cout << m[2][2] << std::endl;
return 0;
In main(), m is a pointer to a Matrix object, so you need to dereference the pointer in order to access the Matrix object so you can invoke your Matrix::operator[] on it, eg:
int main()
{
Matrix *m = new Matrix(5, 5);
(*m)[2][2] = "It Works";
std::cout << (*m)[2][2] << std::endl;
delete m;
return 0;
}
Online Demo
Otherwise, the pointer is not really needed in your example to begin with, eg:
int main()
{
Matrix m(5, 5);
m[2][2] = "It Works";
std::cout << m[2][2] << std::endl;
return 0;
}
Online Demo
Either way, your Proxy does not need to implement operator= at all, eg:
class Proxy {
std::string *mm;
public:
Proxy(std::string *s) : mm(s) {}
std::string& operator[](int index) {
return mm[index];
}
};
A statement like m[2][2] = "..."; will not invoke your Proxy::operator=, it will invoke only Proxy::operator[]. A statement like m[2] = "..."; would be needed to invoke Proxy::operator=, which doesn't make sense to do in a multi-dimensional scenario.
Also, your Matrix constructor has a bug - writing to m[x] is going out of bounds of the m[] array, so the array is not actually filled at all, and you are corrupting surrounding memory, and leaking memory. You need to write to m[i] instead:
//m[x] = new std::string[y];
m[i] = new std::string[y];
After fixing that, Matrix is still leaking memory, as it does not implement a destructor to free the std::strings. You must delete[] anything you new[] (same with delete and new).
And then, you should finish off implementing support for the Rule of 3/5/0, by implementing a copy constructor and a copy assignment operator (your example code does not need them, but production code should always have them), eg:
#include <iostream>
#include <string>
#include <utility>
class Matrix {
std::string **m;
int m_x, m_y;
public:
Matrix(int x = 0, int y = 0) : m_x(x), m_y(y) {
m = new std::string*[x];
for (int i = 0; i < x; ++i)
m[i] = new std::string[y];
}
Matrix(const Matrix &src) : m_x(src.m_x), m_y(src.m_y) {
m = new std::string*[m_x];
for (int i = 0; i < m_x; ++i) {
m[i] = new std::string[m_y];
for (int j = 0; j < m_y; ++j) {
m[i][j] = src.m[i][j];
}
}
}
~Matrix() {
for (int i = 0; i < m_x; ++i)
delete[] m[i];
delete[] m;
}
Matrix& operator=(const Matrix &rhs) {
if (&rhs != this) {
Matrix temp(rhs);
std::swap(m, temp.m);
std::swap(m_x, temp.m_x);
std::swap(m_y, temp.m_y);
}
return *this;
}
class Proxy {
std::string *mm;
public:
Proxy(std::string *s) : mm(s) {}
std::string& operator[](int index) {
return mm[index];
}
};
Proxy operator[](int index) {
return Proxy(m[index]);
}
};
int main()
{
Matrix m(5, 5);
m[2][2] = "It Works";
std::cout << m[2][2] << std::endl;
Matrix m2(m);
std::cout << m2[2][2] << std::endl;
Matrix m3;
m3 = m2;
std::cout << m3[2][2] << std::endl;
return 0;
}
Online Demo
However, rather than using new[] manually, consider using std::vector instead (which you are already aware of, since you have #include <vector> in your code). This way, the Rule of 3/5/0 can be handled entirely by the compiler for you. std::vector and std::string are both fully compliant with the Rule, and so any compiler-generated destructor, copy constructor, and copy-assignment operator in Matrix will suffice, eg:
#include <iostream>
#include <vector>
#include <string>
class Matrix {
std::vector<std::vector<std::string>> m;
public:
Matrix(int x = 0, int y = 0) {
m.resize(x);
for (int i = 0; i < x; ++i)
m[i].resize(y);
}
class Proxy {
std::vector<std::string> &mm;
public:
Proxy(std::vector<std::string> &s) : mm(s) {}
std::string& operator[](int index) {
return mm[index];
}
};
Proxy operator[](int index) {
return Proxy(m[index]);
}
};
Online Demo

Modifying value of object pointed by a shared pointer

I have recently started working with shared pointers and need some help. I have a vector 1 of shared pointers to some objects. I need to construct another vector 2 of shared pointers to the same objects, so that modifying vector 2 would result in modification of vector 2.
This is how my code looks like:
This works fine
class A
{
public:
int a;
A (int x) {
a = x;
}
int print() {
return a;
}
};
int main()
{
shared_ptr<A> ab = make_shared<A>(100);
cout<< ab->print();
shared_ptr<vector<shared_ptr<A>>> vec1 = make_shared<vector<shared_ptr<A>>>(1);
shared_ptr<vector<shared_ptr<A>*>> vec2 = make_shared<vector<shared_ptr<A>*>>();
vec2->push_back(&(*vec1)[0]);
for (shared_ptr<A>* obj : *vec2) {
*obj = make_shared<A>(100);
}
cout << (*((*vec1)[0])).a; // Prints 100
return 0;
}
But this gives a SEGV at the last line since vec1 is not populated:
class A
{
public:
int a;
A (int x) {
a = x;
}
int print() {
return a;
}
};
int main()
{
shared_ptr<vector<shared_ptr<A>>> vec1 = make_shared<vector<shared_ptr<A>>>(1);
shared_ptr<vector<shared_ptr<A>>> vec2 = make_shared<vector<shared_ptr<A>>>();
vec2->push_back((*vec1)[0]);
for (shared_ptr<A> obj : *vec2) {
obj = make_shared<A>(100);
}
cout << (*((*vec1)[0])).a; // SIGSEGV
return 0;
}
I want to understand why vec1 was not populated in the 2nd one and also would like to know if there is any other way of doing this. Thanks!
The code for the setup described in the comments could be:
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
struct A
{
int a;
A(int a): a(a) {}
};
int main()
{
auto p_vec1 = make_shared<vector<shared_ptr<A>>>();
auto p_vec2 = make_shared<vector<shared_ptr<A>>>();
for (int i = 0; i < 100; ++i)
p_vec1->push_back( make_shared<A>(i) );
for (int i = 0; i < 50; ++i)
p_vec2->push_back( (*p_vec1)[i * 2] );
(*p_vec1)[2]->a = 213;
std::cout << (*p_vec2)[1]->a << '\n'; // print 213
return 0;
}
In case you are unaware, the "outer" shared_ptr is unnecessary, you could just use two vectors .

function pointer for different functions with different data types or parameter

i have this code which uses a function pointer to point 3 functions sum, subtract, mul. it works well. but now the problem is that i have functions with different no.of parameters and different data types. how to implement this.
int add(int a, int b)
{
cout<<a+b;
}
int subtract(int a, int b)
{
cout<<a-b;
}
int mul(int a, int b)
{
cout<<a*b;
}
int main()
{
int (*fun_ptr_arr[])(int, int) = {add, subtract, mul};
unsigned int ch, a = 15, b = 10,c=9;
ch=2;
if (ch > 4) return 0;
(*fun_ptr_arr[ch])(a, b);
return 0;
}
The simple answer is that technically you can't do this. You could do some manipulations using an array as input for all these functions, but you will still have to know exactly what to pass to each function. From a software engineering perspective, you should not do this - I suggest you take a look at the nice answers here: C++ Function pointers with unknown number of arguments
A slightly different approach using objects to implement the required behavior. In order to have a truly generic kind of solution, we need to use Interfaces.
Dismantle the data and operation i.e keep them separately.
//Interface which describes any kind of data.
struct IData
{
virtual ~IData()
{
}
};
//Interface which desribes any kind of operation
struct IOperation
{
//actual operation which will be performed
virtual IData* Execute(IData *_pData) = 0;
virtual ~IOperation()
{
}
};
Now, every operation knows the kind of data it work on and will expect that kind of data only.
struct Operation_Add : public IOperation
{
//data for operation addition.
struct Data : public IData
{
int a;
int b;
int result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Add::Data_Add"
Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = pData->a + pData->b;
return pData;
}
};
struct Operation_Avg : public IOperation
{
//data for operation average of numbers.
struct Data : public IData
{
int a[5];
int total_numbers;
float result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Avg::Data_Avg"
Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = 0.0f;
for(int i = 0; i < pData->total_numbers; ++i)
{
pData->result += pData->a[i];
}
pData->result /= pData->total_numbers;
return pData;
}
};
Here, is the operation processor, the CPU.
struct CPU
{
enum OPERATION
{
ADDITION = 0,
AVERAGE
};
Operation_Add m_stAdditionOperation;
Operation_Avg m_stAverageOperation;
map<CPU::OPERATION, IOperation*> Operation;
CPU()
{
Operation[CPU::ADDITION] = &m_stAdditionOperation;
Operation[CPU::AVERAGE] = &m_stAverageOperation;
}
};
Sample:
CPU g_oCPU;
Operation_Add::Data stAdditionData;
stAdditionData.a = 10;
stAdditionData.b = 20;
Operation_Avg::Data stAverageData;
stAverageData.total_numbers = 5;
for(int i = 0; i < stAverageData.total_numbers; ++i)
{
stAverageData.a[i] = i*10;
}
Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData));
if(pResultAdd != NULL)
{
printf("add = %d\n", pResultAdd->result);
}
Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData));
if(pResultAvg != NULL)
{
printf("avg = %f\n", pResultAvg->result);
}
If you have the following functions
int f1(int i);
int f2(int i, int j);
You can define a generic function type like this
typedef int (*generic_fp)(void);
And then initialize your function array
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
But you will have to cast the functions back
int result_f1 = ((f1) func_arr[0]) (2);
int result_f2 = ((f2) func_arr[1]) (1, 2);
Obviously, it does not look like a good way to build a program
To make code look a little bit better you can define macros
#define F1(f, p1) ((f1)(f))(p1)
#define F2(f, p1, p2) ((f2)(f))(p1, p2)
int result_f1 = F1(func_arr[0], 2);
int result_f2 = F2(func_arr[1], 1, 2);
EDIT
Forgot to mention, you also have to define a type for every type of function
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
And to then cast stored pointers to those types
int result_f1 = ((fi) func_arr[0]) (2);
int result_f2 = ((fii) func_arr[1]) (1, 2);
Here is a complete example
#include <iostream>
typedef int (*generic_fp)(void);
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
#define F1(f, p1) ((fi)(f))(p1)
#define F2(f, p1, p2) ((fii)(f))(p1, p2)
int f1(int i);
int f2(int i, int j);
int main()
{
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
int result_f1_no_macro = ((fi) func_arr[0]) (2);
int result_f2_no_macro = ((fii) func_arr[1]) (1, 2);
int result_f1_macro = F1(func_arr[0], 2);
int result_f2_macro = F2(func_arr[1], 1, 2);
std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl;
std::cout << result_f1_macro << ", " << result_f2_macro << std::endl;
return 0;
}
int f1(int i)
{
return i * 2;
}
int f2(int i, int j)
{
return i + j;
}
The code above produces the following output
4, 3
4, 3

c++ copy assignment operator classes

I have a problem with the operator = in my class. This is the semplified code:
class:
#include <iostream>
using namespace std;
class Mat{
private:
int *m1;
int *m2;
unsigned rows;
unsigned cols;
void write(unsigned r_max, unsigned c_max){
m1 = new int [r_max*c_max];
for(unsigned i = 0; i < r_max*c_max; i++){
m1[i] = i;
}
}
public:
Mat():
rows(1), cols(1){
m1 = new int [1];
m1[0] = 0;
m2 = new int [1];
m2[0] = 0;
}
Mat(unsigned r, unsigned c):
rows(r), cols(c){
write(rows, cols);
m2 = new int [rows*cols];
for(unsigned i = 0; i < rows*cols; i++)
m2[i] = 0;
}
Mat &operator=(const Mat &w){
int *new_ptr1 = NULL;
new_ptr1 = new int [w.rows*w.cols];
int *new_ptr2 = NULL;
new_ptr2 = new int [w.rows*w.cols];
for(unsigned i = 0; i < w.rows*w.cols; i++){
new_ptr1[i] = w.say_m1(i);
new_ptr2[i] = w.say_m2(i);
}
delete[] w.m1;
delete[] w.m2;
m1 = new_ptr1;
m2 = new_ptr2;
rows = w.rows;
cols = w.cols;
return *this;
}
int say_m1(unsigned i) const{ return m1[i]; }
int say_m2(unsigned i) const{ return m2[i]; }
~Mat(){
delete[] m1;
delete[] m2;
}
};
Here is what I need to do in the main:
#include "Mat.cpp"
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char **argv){
Mat a;
Mat b(20, 20);
a = b;
return 0;
}
I think the problem is in the class where I overload the operator =
I don't know how to copy the right object data into the left object data, I'm not sure also if I delete correctly...
I think the problem is in the class where I overload the operator = I don't know how to copy the right object data into the left object data, I'm not sure also if I delete correctly...
You do not (delete correctly).
Operator = should alter the values of *this. Instead, you delete w.m1 and w.m2 (where w is your parameter).
Corrected code:
Mat &operator=(const Mat &w){
int *new_ptr1 = NULL;
new_ptr1 = new int [w.rows*w.cols];
int *new_ptr2 = NULL;
new_ptr2 = new int [w.rows*w.cols];
for(unsigned i = 0; i < w.rows*w.cols; i++){
new_ptr1[i] = w.say_m1(i);
new_ptr2[i] = w.say_m2(i);
}
delete[] m1; // <<< HERE
delete[] m2; // <<< HERE
m1 = new_ptr1;
m2 = new_ptr2;
rows = w.rows;
cols = w.cols;
return *this;
}
That said, there's a host of other problems with your code:
Assuming you wrote this code to learn how to manipulate dynamic arrays within a class:
you're using a class that manages two different allocated resources directly. You should consider using a smart pointer on m1 and m2 (for exception safety).
Implement the rule of three: constructor (you already have this), copy constructor (you don't have this) and assignment operator (you already have this).
Add a destructor to your class.
** Assuming this is code you will use and did not write for learning arrays:**
[] use std::vectors for m1 and m2 instead. This will save you from having to implement the rule of three and destructor.
You use using namespace std; globally. Don't do that as it creates many many problems.
Edit:
Better code:
#include <iostream>
#include <vector>
class Mat{
std::vector<int> life;
std::vector<int> neighborhood;
public:
// this is unnecessary
// void write(unsigned r_max, unsigned c_max); {
Mat() : life(1), meighborhood(1) // fill each with 1 int with default value (0)
{
}
Mat(unsigned r, unsigned c)
: life(r), meighborhood(c) // fill each with r(and c) ints with default value (0)
{
}
// ~Mat() became unnecessary: destructors of std::vector will deallocate fine
Mat &operator=(const Mat &w) {
// create replacements before doing changing any value
// this way, if you get an exception while creating the data
// the value in the obhect does not change
std::vector<int> new_life(w.life);
std::vector<int> new_neighborhood(w.neighborhood);
life.swap(new_life);
neighborhood.swap(new_neighborhood);
return *this;
}
// use std::vector<int>::at which throws an exception if the index is invalid
// if you are not interested in the validation of the index
// return life[i] and neighborhood[i]
int say_m1(unsigned i) const{ return life.at(i); }
int say_m2(unsigned i) const{ return neighborhood.at(i); }
};

Template, inheritance and operators

I have some trouble with class template inheritance and operators (operator +),
please have a look at these lines:
Base vector class (TVector.h):
template<class Real, int Size>
class TVector {
protected:
Real* values;
public:
...
virtual TVector<Real, Size>& operator=(const TVector<Real, Size>& rTVector) { //WORKS
int i = 0;
while (i<Size) {
*(values+i) = *(rTVector.values+i);
i++;
}
return *this;
}
virtual TVector<Real, Size> operator+(const TVector<Real, Size>& rTVector) const {
int i = 0;
Real* mem = (Real*)malloc(sizeof(Real)*Size);
memcpy(mem, values, Size);
while (i<Size) {
*(mem+i) += *(rTVector.values+i);
i++;
}
TVector<Real, Size> result = TVector<Real, Size>(mem);
free(mem);
return result;
}
};
2D vector class (TVector2.h):
template<class Real>
class TVector2: public TVector<Real, 2> {
public:
...
TVector2& operator=(const TVector2<Real>& rTVector) { //WORKS
return (TVector2&)(TVector<Real, 2>::operator=(rTVector));
}
TVector2 operator+(TVector2<Real>& rTVector) const { //ERROR
return (TVector2<Real>)(TVector<Real, 2>::operator+(rTVector));
}
};
Test (main.cpp):
int main(int argc, char** argv) {
TVector2<int> v = TVector2<int>();
v[0]=0;
v[1]=1;
TVector2<int> v1 = TVector2<int>();
v1.X() = 10;
v1.Y() = 15;
v = v + v1; //ERROR ON + OPERATOR
return 0;
}
Compilation error (VS2010):
Error 2 error C2440: 'cast de type' : cannot convert from
'TVector<Real,Size>' to 'TVector2' ...
What is wrong here ? is there a way to do this kind of stuff ?
Just looking for a way to not redefine all my Vectors classes.
I keep searching to do it, but I will be glad to get some help from you guys.
Sorry for bad English,
Best regards.
#include <memory>
using namespace std;
template<class Real, int Size> class TVector {
protected:
Real *_values;
public:
TVector() {
// allocate buffer
_values = new Real[Size];
}
TVector(Real *prValues) {
// check first
if (prValues == 0)
throw std::exception("prValues is null");
// allocate buffer
_values = new Real[Size];
// initialize buffer with values
for (unsigned int i(0U) ; i < Size ; ++i)
_values[i] = prValues[i];
}
// Do not forget copy ctor
TVector(TVector<Real, Size> const &rTVector) {
// allocate buffer
_values = new Real[Size];
// initialize with other vector
*this = rTVector;
}
virtual ~TVector() {
delete [] _values;
}
virtual Real &operator[](int iIndex) {
// check for requested index
if (iIndex < 0 || iIndex >= Size)
throw std::exception("requested index is out of bounds");
// index is correct. Return value
return *(_values+iIndex);
}
virtual TVector<Real, Size> &operator=(TVector<Real, Size> const &rTVector) {
// just copying values
for (unsigned int i(0U) ; i < Size ; ++i)
_values[i] = rTVector._values[i];
return *this;
}
virtual TVector<Real, Size> &operator+=(TVector<Real, Size> const &rTVector) {
for (unsigned int i(0U) ; i < Size ; ++i)
_values[i] += rTVector._values[i];
return *this;
}
virtual TVector<Real, Size> operator+(TVector<Real, Size> const &rTVector) {
TVector<Real, Size> tempVector(this->_values);
tempVector += rTVector;
return tempVector;
}
};
template<class Real> class TVector2: public TVector<Real, 2> {
public:
TVector2() {};
TVector2(Real *prValues): TVector(prValues) {}
TVector2 &operator=(TVector2<Real> const &rTVector) {
return static_cast<TVector2 &>(TVector<Real, 2>::operator=(rTVector));
}
TVector2 &operator+=(TVector2<Real> const &rTVector) {
return static_cast<TVector2 &>(TVector<Real, 2>::operator+=(rTVector));
}
TVector2 operator+(TVector2<Real> const &rTVector) {
return static_cast<TVector2 &>(TVector<Real, 2>::operator+(rTVector));
}
Real &X() { return _values[0]; }
Real &Y() { return _values[1]; }
};
int main(int argc, char** argv) {
TVector2<int> v = TVector2<int>();
v[0]=0;
v[1]=1;
TVector2<int> v1 = TVector2<int>();
v1.X() = 10;
v1.Y() = 15;
v = v1;
v += v1;
v = v + v1;
return 0;
}
Some misc notes:
it's very bad that you use malloc against of new. Real can be POD only to allow vector work well in your case. Use new or provide custom creation policy if you think that malloc provides better performance on PODs. Also do not forget to use delete [] instead of free while destroying memory buffer.
It's better to perform bounds checking while overloading operator[]
for better performance use ++i instead of postfix form. In former no temporary value is created.