Using member functions to deal with objects in the heap (c++) - c++

I'm a beginner with C++, and this is a pretty basic syntax question, but i can't seem to find an answer elsewhere. Any input would be welcome. Here is a simplified version of the problem.
Say I have a class 'pair'
class pair
{
int a;
int b;
public:
pair(int x,int y)
{
a=x;
b=y;
}
int lookup()
{
return this->a+b;
}
};
Then i instanciate and copy that instance to a spot on the heap.
int func()
{
...
pair test(1,2);
pair *ptr=new pair;
*ptr=test;
}
Now here is the key. I don't destroy this memory allocation after the function ends. I want to use it later in this other function. The problem is, i would prefer to keep it in the heap and NOT have to copy it over to the stack(in the actual program it is very large). I would therefore like to do something like this:
int otherfunc()
{
...
int sum=*ptr.lookup;
}
but I get a compiler error. I end up having to do something like:
int otherfunc()
{
...
point temp=*ptr;
int sum=temp.lookup;
}
While this works, it is redundant, and when dealing with really large things it can even potentially cause an overflow. Anyone know the syntax for calling the method using the pointer while keeping it on the heap? Thanks.

I believe this is what you are trying to do:
int sum = ptr->lookup();
And as an aside, this:
return this->a+b;
Would probably be better as just this:
return a+b;

The expression *ptr.lookup will be interpreted as *(ptr.lookup), which is why you get the syntax error because ptr.lookup does not make sense. You'll need to tell the compiler dereference ptr first by using the parenthesis: (*ptr).lookup.
Because pointers are common in C (and C++), the (*a).b can be written in a simpler form: a->b.
Also, lookup is a function even if it does not take any parameters. You need to call it with ():
int sum=ptr->lookup();

Related

How to do always the same things just before 'return' when a function has a lot of 'return's?

I've a big function which allocates 2 arrays in the heap memory and returns many times in many different places. I would like to make the function call delete[] for my 2 arrays whenever she returns, without having to write delete[]s before each return.
int function(int a)
{
size_t heap_arr1_len{100};
int* heap_arr1{new int[heap_arr1_len]};
size_t heap_arr2_len{200};
int* heap_arr2{new int[heap_arr2_len]};
//I was thinking of something similar to:
struct at_return{
~at_return()
{
delete[] heap_arr1;
delete[] heap_arr2;
}
} at_return;
/*...............
.................
......return 0;*/
/*...............
.....return 10;*/
//ecc.
}
but with a compilation-time error i've figured out that a struct can't access the local variables of the function which is contained in.
What would you do in order to avoid to having to write delete[] heap_arr1;, delete[] heap_arr2; each time before each return?
Don't allocate memory manually using new, use std::vector instead:
size_t heap_arr1_len = 100;
std::vector<int> heap_arr1(heap_arr1_len);
Then you don't need to worry about delete.
But using a destructor like this is in fact a great idea, assuming no suitable wrapper class exists. This trick is known as a scope guard. And here's a working implementation.
It could be useful e.g. when dealing with C libraries, which can't provide classes with destructors. You could write a reusable wrapper class with a destructor, or you could use a scope guard as an ad-hoc solution.
#include <memory>
int function(int a)
{
size_t heap_arr1_len{100};
std::unique_ptr<int[]> heap_arr1{new int[heap_arr1_len]};
// Etc
}
If you need the underlying pointer for your file reading/writing functions, use heap_arr1.get().
I use a can_continue method so there is only one entry and one exit (MISRA rule).
First set a Boolean variable:
bool can_continue = true;
The pattern then becomes:
if (can_continue)
{
// do some work
// set can_continue to false to return unexpectedly
}
It may not be the fastest code, but it meets the criteria for one entry and one exit.

returning a 2D arrray in c++

I recentley started coding in C++ and I can't seem to understand how to ruturn the 2d array
GridArray
Is the problem somewhere in the type of the method because I can't seem to resolve it. Any help would be much appriciated!
static int GridArray [15][20];
int MapEditor::updateGrid(int *xCursor,int *yCursor){`
int width=16;
if(input.getInput()==psxUp){
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,255 );
(*yCursor)--;
if((*yCursor)<=0){
(*yCursor)=15;
}
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,224 );
}
if(input.getInput()==psxLeft){
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,255 );
(*xCursor)--;
if((*xCursor)<=0){
(*xCursor)=20;
}
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,224 );
}
if(input.getInput()==psxRight){
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,255 );
(*xCursor)++;
if((*xCursor)>=20){
(*xCursor)=0;
}
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,224 );
}
if(input.getInput()==psxDown){
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,255 );
(*yCursor)++;
if((*yCursor)>=15){
(*yCursor)=0;
}
VGA.drawRect((*xCursor)*16,(*yCursor)*16,(*xCursor)*16+width,(*yCursor)*16+width,224 );
}
if(input.getInput()==psxSqu){
spriteSelector.setSprite(bricks_destructive,bricks_destructive_palette);
spriteSelector.drawAtPosition((*xCursor)*16,(*yCursor)*16);
spriteSelector.update();
GridArray[(*yCursor)][(*xCursor)]=1;
Serial.println(GridArray[(*yCursor)][(*xCursor)]);
}
delay(120);
if(input.getInput()==psxSlct){
Serial.println(GridArray);
return GridArray;
}
}
In C++ you cannot return plain arrays (neither 1D ones nor 2D ones or higher). One could return a reference to such an array, and it would even be possible to encapsulate such arrays in a struct-object (which then could be returned).
However, these solutions are probably a work around of what is actually intended.
As you start coding C++ you might start with abandoning "old fashioned C style" and make use of the C++ concepts like standard library and its containers, e.g. with std::array. With that, you' code above example differently:
#include <array>
typedef std::array<std::array<int,15>,20> GridArray;
GridArray initGrid() {
GridArray ga = { { 0 } };
ga[0][0] = 15;
ga[0][1] = 30;
return ga;
}
int main() {
GridArray g = initGrid();
for(auto row : g) {
for (auto column : row) {
cout << column << " ";
}
cout << endl;
}
}
Note that there are other variants as well (e.g. passing arrays in as input parameters to functions which then alter them rather then creating and returning them in the function. But actually I think that the std::array-approach comes closest to that what you need.
I assume you are getting compile errors?
You have 2 problems:
The return type of your function is int but you are trying to return int
[15][20]
You aren't allowed to return an array from a function
Not all code paths return a value, your return GridArray needs to be outside the if statement.
you probably want something like this:
typedef int ArrayType[15][20];
static ArrayType GridArray;
ArrayType& f()
{
...
return GridArray;
}
Or even better use std::vector or std::array
Here is another solution, and it gets overlooked for more "technical" solutions, but this solution is rather simple.
This solution doesn't require intimate knowledge of pointers or references, doesn't require knowledge or usage of STL, doesn't require features or libraries that exist in standard C++ that may not exist on some platforms, should be very lightweight, and should be easily understandable by even beginner C++ programmers. However there is some code you would need to change to apply this technique.
The solution is this: simply wrap the 2-dimensional array inside a struct and pass / return the struct. That's it.
Since a struct is copyable and assignable (and arrays are neither one), then it is simply a matter of wrapping the array inside a struct and use that as a poor-man's container (even though it just works). Copies work, assignments work, passing to and from functions work, etc.
struct Array2D
{
int GridArray [15][20];
};
Then you simply pass and return Array2D's around. No pointers are necessary.
static Array2D theGrid;
Array2D& SomeFunction()
{
...
theGrid.GridArray[(*yCursor)][(*xCursor)]=1;
return theGrid;
}
The above returns a reference to the Array2D that was declared static. But you also get a choice of returning a copy of the results is so desired.
Array2D SomeFunction2()
{
...
theGrid.GridArray[(*yCursor)][(*xCursor)]=1;
return theGrid;
}
The above takes the static Array2D that was declared and returns a copy of it.
You then have the power to do things like:
Array2D tempGrid = theGrid; // get a copy of the original
//..
tempGrid.GridArray[0][0] = 1; // changes the copy but not the original
No need for for loops or memcpy's to assign one array to the other -- let the struct do that work automatically and easily for you since assignment and copy is built-in with structs and classes.
But again please note that you will need to change some code around to append xyz. to your current code that refers to GridArray, where xyz is the name of the Array2D instance.

Best way to return pointer to nested std::vector items

In the block of code below I would like to refactor so I'm returning an array of three pointers to a vector of doubles. I'm a little confused as the best way to do this.
If the error is hit, i'd also like it to be easy to detect from the calling function.
Do I need to convert the vCase var into something like:
std::vector<double>[3] vCases
// or
double[3] vCases
Also whats the correct function definition for this? I get the basics of Arrays, the fact i've got a nested vector is whats throwing me!
any help gratefully recieved.
std::vector<std::vector<double> > TrainingCases::getCase(int caseNo) {
std::vector<std::vector<double> > vCase;
if (caseNo > vInputs.size()) {
std::cout << "TrainingCases Error: Out of range caseNo selected. " << std::endl;
return vCase;
} else {
vCase.push_back(vInputs.at(caseNo));
vCase.push_back(vTargets.at(caseNo));
vCase.push_back(vScoreModifiers.at(caseNo));
return vCase;
}
}
I'm really not sure if I get what you want to accomplish... Anyway, the following would certainly work:
vector<vector<double>> getCase()
{
vector<vector<double>> vCase;
return vCase;
}
If you want to kind of return a pointer to an array of vectors, the following would do:
vector<double>* getCase()
{
vector<double>* vCase = new vector<double>[3];
return vCase;
}
But that would be a very bad idea, since you would have to call delete[] on the returned pointer somewhere to prevent a memory leak. A better option would be to write
struct CaseType
{
vector<double> vCase[3];
};
CaseType getCase()
{
CaseType myCase;
return myCase;
}
The point is, you cannot create a temporary stack object inside your function and then return a pointer to it, since it will be automatically destructed. If you create the object using new however you will have to free the memory somewhere, and I wouldn't write code like that (in this case).
Edit
Judging from you comment, I believe you want something like this:
struct CaseType
{
vector<double> vCase[3];
};
void getCase(CaseType& myCase)
{
// myCase.vCase[0] = ...
// myCase.vCase[1] = ...
// ...
}
This way you don't have to construct temporary objects all the time. You would call you function like that:
CaseType myCase;
getCase(myCase);
// do stuff with myCase
You can't return a built-in array, mainly because they are not copyable when on themselves (built-in arrays are copyable when they are a member of something). The easiest way may be to return a std::array<std::vector<double>, 3> instead:
return std::array<std::vector<double>, 3>{ vInputs[caseNo],
vTargets[caseNo],
vScoreModifiers[caseNo] };
For the case that the index is out of range I would throw an exception. Of course, if you actually use want to return pointers and the objects stay around long enough, you'd use a slightly modified version:
return std::array<std::vector<double> const*, 3>{ &vInputs[caseNo],
&vTargets[caseNo],
&vScoreModifiers[caseNo] };
The const is optional but the things you return sound as if they are not getting modified.

How to modify a C++ structure with int *

I have the following structure:
struct CountCarrier
{
int *CurrCount;
};
And this is what I want to do:
int main()
{
CountCarrier carrier = CountCarrier();
*(carrier.CurrCount) = 2; // initialize the *(carrier.CurrCount) to 2
IncreaseCount(&carrier); // should increase the *(carrier.CurrCount) to 3
}
void IncreaseCount(CountCarrier *countCarrier)
{
int *currCounts = countCarrier->CurrCount;
(*currCounts)++;
}
So, my intention is specified in the comments.
However, I couldn't get this to work. For starters, the program throws an exception at this line:
*(carrier.CurrCount) = 2;
And I suspect the following line won't work as well. Anything I did wrong?
struct CountCarrier
{
int *CurrCount; //No memory assigned
};
You need to allocate some valid memory to the pointer inside the structure to be able to put data in this.
Unless you do so, What you ar trying to do is attempting to write at some invalid address, which results in an Undefined Behavior, which luckiy in this case shows up as an exception.
Resolution:
struct CountCarrier
{
int *CurrCount; //No memory assigned
CountCarrier():CurrCount(new(int))
{
}
};
Suggestion:
Stay away from dynamic allocations as long as you can.
When you think of using pointers always think whether you really need one. In this case it doesn't really seem that you need one, A simple int member would be just fine.
You need to create the pointer. ie. carrier->CurrCount = new int;
*(carrier.CurrCount)
This is dereferencing the pointer carrier.CurrCount, but you never initialized it. I suspect this is what you want:
carrier.CurrCount = new int(2);
I seriously doubt that your program throws an exception at the line:
*(carrier.CurrCount) = 2;
While throwing an exception is certainly allowed behaviour, it seems much more likely that you encountered an access violation that caused the process to be killed by the operating system.
The problem is that you are using a pointer, but your pointer is not initialised to point at anything. This means that the result of the pointer dereference is undefined.
In this situation there does not seem to be any advantage to using a pointer at all. Your CurrCount member would work just as well if it was just a plain int.
If you are using C++, then you should encash its facilities. Instead of correcting your code, I am showing here that how the code should look like:
struct CountCarrier
{
int CurrCount; // simple data member
CountCarrier(int count) : CurrCount(count) {} // constructor
CountCarrier& operator ++ () // overloaded operator
{
++ CurrCount;
return *this;
}
};
We are overloading operator ++, because you have only one data member. You can replace with some named method also, like void IncrementCount().
CountCarrier carrier(2);
++ carrier;
As Als said, you need to provide some memory for the code to work.
But why make it so complicated? You don't need any pointers for the code you have to work. The "modern C++" way looks more like this:
struct CountCarrier
{
public:
CountCarrier(int currCount) : currCount(currCount) {}
void IncreaseCount() { ++currCount; }
int GetCount() const { return currCount; }
private:
int currCount;
};
int main()
{
CountCarrier carrier(2); // Initialize carrier.currCount to 2
carrier.IncreaseCount(); // Increment carrier.currCount to 3
}
Note how much cleaner and less error prone that is. Like I said, pick up a good introductory C++ book and read through it.

Creating function pointers to functions created at runtime

I would like to do something like:
for(int i=0;i<10;i++)
addresses[i] = & function(){ callSomeFunction(i) };
Basically, having an array of addresses of functions with behaviours related to a list of numbers.
If it's possible with external classes like Boost.Lambda is ok.
Edit: after some discussion I've come to conclusion that I wasn't explicit enough. Please read Creating function pointers to functions created at runtime
What I really really want to do in the end is:
class X
{
void action();
}
X* objects;
for(int i=0;i<0xFFFF;i++)
addresses[i] = & function(){ objects[i]->action() };
void someFunctionUnknownAtCompileTime()
{
}
void anotherFunctionUnknowAtCompileTime()
{
}
patch someFunctionUnknownAtCompileTime() with assembly to jump to function at addresses[0]
patch anotherFunctionUnknownAtCompileTime() with assembly to jump to function at addresses[1]
sth, I don't think your method will work because of them not being real functions but my bad in not explaining exactly what I want to do.
If I understand you correctly, you're trying to fill a buffer with machine code generated at runtime and get a function pointer to that code so that you can call it.
It is possible, but challenging. You can use reinterpret_cast<> to turn a data pointer into a function pointer, but you'll need to make sure that the memory you allocated for your buffer is flagged as executable by the operating system. That will involve a system call (LocalAlloc() on Windows iirc, can't remember on Unix) rather than a "plain vanilla" malloc/new call.
Assuming you've got an executable block of memory, you'll have to make sure that your machine code respects the calling convention indicated by the function pointer you create. That means pushing/popping the appropriate registers at the beginning of the function, etc.
But, once you've done that, you should be able to use your function pointer just like any other function.
It might be worth looking at an open source JVM (or Mono) to see how they do it. This is the essence of JIT compilation.
Here is an example I just hacked together:
int func1( int op )
{
printf( "func1 %d\n", op );
return 0;
}
int func2( int op )
{
printf( "func2 %d\n", op );
return 0;
}
typedef int (*fp)(int);
int main( int argc, char* argv[] )
{
fp funcs[2] = { func1, func2 };
int i;
for ( i = 0; i < 2; i++ )
{
(*funcs[i])(i);
}
}
The easiest way should be to create a bunch of boost::function objects:
#include <boost/bind.hpp>
#include <boost/function.hpp>
// ...
std::vector< boost::function<void ()> > functors;
for (int i=0; i<10; i++)
functors.push_back(boost::bind(callSomeFunction, i));
// call one of them:
functors[3]();
Note that the elements of the vector are not "real functions" but objects with an overloaded operator(). Usually this shouldn't be a disadvantage and actually be easier to handle than real function pointers.
You can do that simply by defining those functions by some arbitrary names in the global scope beforehand.
This is basically what is said above but modifying your code would look something like this:
std::vector<int (*) (int)> addresses;
for(int i=0;i<10;i++) {
addresses[i] = &myFunction;
}
I'm not horribly clear by what you mean when you say functions created at run time... I don't think you can create a function at run time, but you can assign what function pointers are put into your array/vector at run time. Keep in mind using this method all of your functions need to have the same signature (same return type and parameters).
You can't invoke a member function by itself without the this pointer. All instances of a class have the function stored in one location in memory. When you call p->Function() the value of p is stored somewhere (can't remember if its a register or stack) and that value is used as base offset to calculate locations of the member variables.
So this means you have to store the function pointer and the pointer to the object if you want to invoke a function on it. The general form for this would be something like this:
class MyClass {
void DoStuf();
};
//on the left hand side is a declaration of a member function in the class MyClass taking no parameters and returning void.
//on the right hand side we initialize the function pointer to DoStuff
void (MyClass::*pVoid)() = &MyClass::DoStuff;
MyClass* pMyClass = new MyClass();
//Here we have a pointer to MyClass and we call a function pointed to by pVoid.
pMyClass->pVoid();
As i understand the question, you are trying to create functions at runtime (just as we can do in Ruby). If that is the intention, i'm afraid that it is not possible in compiled languages like C++.
Note: If my understanding of question is not correct, please do not downvote :)