Cannot carry object to function properly C++ - c++

cliques is my class object. All my class commands work when I use them in my main but for some reason I cannot make changes to my heaps or stacks through my functions. I tried using reference markers on my function parameters but still I'm having ussues. Maybe I've done the reference incorrectly. Does anyone have any ideas what I might be doing wrong?
This is one of my functions:
void UpdateTopK(cliques C, vector<cliques> minheap) {
if (C.getclique_size() < CliqueSize) {
return;
}
else if (minheap.size() < Solutions) {
minheap.push_back(C);
push_heap(minheap.begin(), minheap.end(), min_iterator());
}
else if (minheap.size() == Solutions and C.getMaxclique_prob() > minheap.front().getMaxclique_prob()) {
pop_heap(minheap.begin(), minheap.end(), min_iterator());
minheap.pop_back();
minheap.push_back(C);
push_heap(minheap.begin(), minheap.end(), min_iterator());
}
This is part of my main:
stack <cliques> cstack;
vector<cliques> max_heap;
make_heap(max_heap.begin(), max_heap.end(), max_iterator());
vector<cliques> min_heap;
make_heap(min_heap.begin(), min_heap.end(), min_iterator());
for (int i = 0; i < 5; i++) {
cliques temp(i);
cstack.push(temp);
}
while (!cstack.empty()) {
cliques temp = cstack.top();
cstack.pop();
bool pruned = GenerateChildren(temp, min_heap, max_heap, cstack, graph);
if (!pruned) {
UpdateTopK(temp, min_heap);
}
}

You are passing arguments by value, this implies that parameters are copied before being passed to the function.
So every modification inside a method refers to the local copy only. Try passing values by references, eg:
void UpdateTopK(cliques& C, vector<cliques>& minheap)
^ ^
Mind that an object that needs to be passed to a function without copy and without being edited should be passed by const T& to specify this.

Related

How to assign a pointer to object to another pointer to object of same class?

I have a class called arr and it has a function named _union written like this:
template<class T>
arr<T> *arr<T>::_union(arr<T> B) {
arr<T> *C(this->length + B._length());
bool isPresent = false;
for (int i = 0; i < length; i++)
C->push_back(this->get(i));
for (int j = 0; j < B._length(); j++) {
for (int k = 0; k < C->_length(); k++) {
if (B.get(j) == C->get(k))
isPresent = true;
}
if (!isPresent)
C->push_back(B.get(j));
isPresent = false;
}
return C;
}
The function returns a pointer of an object that was newly created inside this function's scope.
In main function, I wrote code like this :
arr<int> *a3 = a1._union(a2);
a3->display();
When I run, this gives me an error:
What is the problem here? If I don't use any pointers and just return normal object then everything is fine.
Please help me. Also I don't have any copy constructers inside the class. I am just trying to create my own array class with data and functions.
In this code
arr<T> *C(this->length + B._length());
C is a pointer and this->length + B._length() is an integer, hence the error. You can't assign an integer to a pointer.
I guess you were trying to write this code
arr<T> *C = new arr<T>(this->length + B._length());
This code allocates a new arr<T> object using new and calls the a constructor for that object using the integer parameter this->length + B._length().
However is usually a bad idea to use dynamic allocation like this. You should think about redesigning your function without using pointers.
template<class T>
arr<T> arr<T>::_union(arr<T> B) {
arr<T> C(this->length + B._length());
...
return C;
}
This will require you to define a copy constructor etc for arr<T>. But that is normal C++ programming you shouldn't be reluctant to do it.

How to pass a function from another class as parameter?

I want to pass a function from another class as parameter in my current class. I'm trying to do something like this (I siplified the code, so you still can get the idea):
B class:
bool B::myCmpFunc(int a, int b) {
return a > b;
}
vector<int> B::sort(bool (*cmp)(int a, int b)) {
vector<int> elems = getElems();
for (int i = 0; i < elems.size() - 1; i++) {
for (int j = i + 1; j < elems.size(); j++) {
if ((*cmp)(elems[i], elems[j])) {
int aux = elems[i];
elems[i] = elems[j];
elems[j] = aux;
}
}
}
return elems;
}
And I try to call this sort function from A class:
B b;
auto sortedElems = b.sort(&b.myCmpFunc);
The problem is I get this error when I try to pass &b.myCmpFunc as parameter in A class:
Error C2276 '&': illegal operation on bound member function
expression
I also tried another things, like passing the function as b.myCmpFunct, B::myCmpFunc, &B::myCmpFunc, but I still got errors.
When you have a class function (non static function inside a class), you need to pass this/the instance of the class around, so the compiler can pass this/the instance of the object to the function, when it invokes it.
You can:
Make your function static. static functions inside a class don't use this / the object instance, so their pointers are normal.
static bool B::myCmpFunc(int a, int b) {}
b.sort(&b.myCmpFunc);
// or
b.sort(&B::myCmpFunc);
You can refactor your function to use std::function and bind this with object pointer using std::bind.
vector<int> B::sort(std::function<bool(int a, int b)> cmp) {
... no changes ...
}
b.sort(std::bind(&B::myCmpFunc, &b, std::placeholders::_1, std::placeholders::_2));
Refactor your function to take only B class functions.
vector<int> B::sort(bool (B::*cmp)(int a, int b)) {
...
(this->*cmp)(...);
...
}
b.sort(&B::myCmpFunc);
Use a lambda.
b.sort([](int a, int b) -> bool { return a < b; });
// really or
b.sort([&b](int a, int b) -> bool { return b.myCmpFunc(a, b); });
and many more (ex. template).
As the member function B::myCmpFunc doesn't seem to use this pointer nor object members, I would go with declaring it static.
You mix up pointers to ordinary functions and pointer to member functions. Those are different concepts, that are worth understanding at some point. What you can do is to make the comparison function a static and then pass a pointer to it like this:
auto sortedElems = b.sort(&B::myCmpFunc);
Otherwise, you can implement myCmpFunc as a free function, i.e., not bound to a class. Then pass it as
auto sortedElems = b.sort(&myFreeCmpFunc);
In any case, it doesn't make much sense to have a member function myCmpFunc that has no dependency on the state of its object. Making it a free function increases encapsulation and makes the comparison function reusable (apart from the fact that you could also use a std::greater<>{} function object instead.

function doesn't change object attributes in c++

I am totally new to c++ and thought it would be good practice to write a program which solved a given liter puzzle (you have 2 containers with capacities of 3 and 5 liters, can you obtain 4 liters? etc.)
I wrote a class for a given container and a function which was intended to 'pour' the contents of one container into another. The function doesn't change the value of the contents of any object however, despite the entire class being public. I'm not sure what I'm doing wrong.
Here is my code:
#include <iostream>
using namespace std;
class Container {
public:
int quantity; //quantity of water in container
int size; //max amt of water
};
void pour(Container a, Container b) {
int differential = b.size - b.quantity;
if (a.quantity <= differential) {
b.quantity = a.quantity + b.quantity;
a.quantity = 0;
}
else if (a.quantity > differential) {
b.quantity = b.quantity - differential;
a.quantity = a.quantity - differential;
}
};
int main() {
Container bottle1;
bottle1.quantity = 5;
bottle1.size = 6;
Container bottle2;
bottle2.quantity = 0;
bottle2.size = 2;
pour(bottle2, bottle1);
cout << bottle1.quantity << ", " << bottle2.quantity << endl;
return 0;
}
I'm sure my mistake is obvious but I can't find an answer anywhere. Any help would be greatly appreciated.
You're passing the Containers as copies. This means that the containers you alter in the pour function are destructed upon function exit.
The solution is to use references:
void pour(Container& a, Container& b)
The & after the type denotes a reference. This means that, instead of copies of a and b being used inside pour, the function gets access to the same a and b as the caller.
This is probably because you're passing the objects by value. You'll want to pass them by reference. You can do this by changing your method header.
Essentially, each instance of Container in the method header should become Container&. The call will not need to be changed.
You can also pass pointers. Your arguments would then become Container *a, and in your call you'd have to add an ampersand (&) before each variable name (e.g. a becomes &a). You'd then also have to change any derefs of the object from periods (.) to arrows (->).
Your method would become:
void pour(Container *a, Container *b) {
int differential = b->size - b->quantity;
if (a->quantity <= differential) {
b->quantity = a->quantity + b->quantity;
a->quantity = 0;
}
else if (a->quantity > differential) {
b->quantity = b->quantity - differential;
a->quantity = a->quantity - differential;
}
};
I mentioned both because in some cases, the designers of a program will adopt the convention that all references are const references. That is, any object passed by reference is not to be modified (which is enforced by using the const keyword before the type name in a method header), and that all other objects are passed by pointer. This makes it more clear, in the function call, whether or not an argument will be modified.
The choice of using a const reference over pass-by-value in that convention is to improve the efficiency of a function call. It is quicker to pass a reference than to make a copy of an object.

Passing a reference to a pointer to pointer of type void

I have a function that accepts a reference to void**.
bool boExecute(void**& vOutParameter);
I tried to write some value in vOutParameter, but when I checked it in the main(), the value was not written.
In this case, what does & referencing to? Is it a reference to a pointer or a reference to a pointer to pointer?
Inside boExecute, I add it like this:
bool boExecute(void**& vOutParameter)
{
Struct_Type* Out = new Struct_Type[4];
for (int i=0; i<4; ++i)
{
memcpy(&(Out[i]), Referenced_Struct[i], sizeof(Struct_Type));
}
*vOutParameter = reinterpret_cast<void*>Out;
Out = null;
return true;
}
Referenced_Struct is of type Struct_Type**, which had two members, int32_val and int64_val.
Contents of main:
void main(void)
{
void **test;
boExecute(test);
Struct_Type** temp = reinterpret_cast<Struct_Type**>(test);
Struct_Type* temp1 = *temp;
for (int i=0; i<4; ++i)
{
printf("%d, %d", temp1[i].int32_val, temp1[i].int64_val);
}
}
Is there something wrong in what I'm doing?
When I changed *vOutParameter, the contents of *vOutParameter should be updated when it goes out of the function, right?
Is there something wrong in what I'm doing?
You should rewrite the function actually using C++, instead of weird C semantic with unnecessary boolean return values for errors and out parameters:
template<typename It>
std::vector<Struct_type> boExecute(It Reference_begin, It Reference_end)
{
std::vector<Struct_type> Out;
std::copy(Reference_begin, Reference_end, std::back_inserter(Out));
return Out;
}
Live demo
Notice that there's no performance issue in returning the whole vector because of RVO (Return Value Optimization). So you can sleep knowing that your memory is safe.
In this case, what does & referencing to? Is it a reference to a pointer or a reference to a pointer to pointer?
In general T& is a reference to T. Which means that void**& is a reference to a void** which is a pointer to pointer to void.

SIGSEGV when trying to acces member of pointer after it was filled by function

The answer is probably stupidly easy, but I have stared at this code for quiet a while now and I simply can't find the solution.
Here is my problem. I have a pointer to a base class. Then I call a function to find an element in a vector of objects derived from that class. The pointer is passed as a parameter and filled with the found object. If I try to read a member variable of what the pointer points to I get a SIGSEV.
This is the code:
Base* control;
if(findControlByName("aName", control)) {
std::cout << control->name << std::endl; // SIGSEV happens here
}
//...
bool findControlByName(std::string name, Base* control) {
for(size_t i = 0; i < controls.size(); i++) {
if(controls[i]->name == name) {
control = controls[i];
std::cout << control->name; // this works
return true;
}
}
return false;
}
How do I do this properly?
To elaborate on my above comment, when you assign a value to a pointer parameter in a function, that value is local to the scope of the function, just like any other parameter that is passed by value. Assigning a value to the parameter in the scope of the function does not change it outside the scope of that function unless it is passed by reference.
An example:
void someFunc(int * x)
{
static int my_static = 5;
x = &my_static;
}
void someFunc2(int * &x)
{
static int my_static_2 = 7;
x = &my_static_2;
}
//somewhere else:
int * ptr;
someFunc(ptr);
//ptr is unchanged/still uninitialized
someFunc2(ptr);
//ptr points to my_static_2
If the signature of someFunc is changed to take a reference parameter, the parameter will be passed by reference instead of passed by value.