returning a 2D arrray in c++ - 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.

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.

C++ understanding RVO (as compared to returning local variable reference)

It's my first year of using C++ and learning on the way. I'm currently reading up on Return Value Optimizations (I use C++11 btw). E.g. here https://en.wikipedia.org/wiki/Return_value_optimization, and immediately these beginner examples with primitive types spring to mind:
int& func1()
{
int i = 1;
return i;
}
//error, 'i' was declared with automatic storage (in practice on the stack(?))
//and is undefined by the time function returns
...and this one:
int func1()
{
int i = 1;
return i;
}
//perfectly fine, 'i' is copied... (to previous stack frame... right?)
Now, I get to this and try to understand it in the light of the other two:
Simpleclass func1()
{
return Simpleclass();
}
What actually happens here? I know most compilers will optimise this, what I am asking is not 'if' but:
how the optimisation works (the accepted response)
does it interfere with storage duration: stack/heap (Old: Is it basically random whether I've copied from stack or created on heap and moved (passed the reference)? Does it depend on created object size?)
is it not better to use, say, explicit std::move?
You won't see any effect of RVO when returning ints.
However, when returning large objects like this:
struct Huge { ... };
Huge makeHuge() {
Huge h { x, y, x };
h.doSomething();
return h;
}
The following code...
auto h = makeHuge();
... after RVO would be implemented something like this (pseudo code) ...
h_storage = allocate_from_stack(sizeof(Huge));
makeHuge(addressof(h_storage));
auto& h = *properly_aligned(h_storage);
... and makeHuge would compile to something like this...
void makeHuge(Huge* h_storage) // in fact this address can be
// inferred from the stack pointer
// (or just 'known' when inlining).
{
phuge = operator (h_storage) new Huge(x, y, z);
phuge->doSomething();
}

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.

return a vector vs use a parameter for the vector to return it

With the code below, the question is:
If you use the "returnIntVector()" function, is the vector copied from the local to the "outer" (global) scope? In other words is it a more time and memory consuming variation compared to the "getIntVector()"-function? (However providing the same functionality.)
#include <iostream>
#include <vector>
using namespace std;
vector<int> returnIntVector()
{
vector<int> vecInts(10);
for(unsigned int ui = 0; ui < vecInts.size(); ui++)
vecInts[ui] = ui;
return vecInts;
}
void getIntVector(vector<int> &vecInts)
{
for(unsigned int ui = 0; ui < vecInts.size(); ui++)
vecInts[ui] = ui;
}
int main()
{
vector<int> vecInts = returnIntVector();
for(unsigned int ui = 0; ui < vecInts.size(); ui++)
cout << vecInts[ui] << endl;
cout << endl;
vector<int> vecInts2(10);
getIntVector(vecInts2);
for(unsigned int ui = 0; ui < vecInts2.size(); ui++)
cout << vecInts2[ui] << endl;
return 0;
}
In theory, yes it's copied. In reality, no, most modern compilers take advantage of return value optimization.
So you can write code that acts semantically correct. If you want a function that modifies or inspects a value, you take it in by reference. Your code does not do that, it creates a new value not dependent upon anything else, so return by value.
Use the first form: the one which returns vector. And a good compiler will most likely optimize it. The optimization is popularly known as Return value optimization, or RVO in short.
Others have already pointed out that with a decent (not great, merely decent) compiler, the two will normally end up producing identical code, so the two give equivalent performance.
I think it's worth mentioning one or two other points though. First, returning the object does officially copy the object; even if the compiler optimizes the code so that copy never takes place, it still won't (or at least shouldn't) work if the copy ctor for that class isn't accessible. std::vector certainly supports copying, but it's entirely possible to create a class that you'd be able to modify like in getIntVector, but not return like in returnIntVector.
Second, and substantially more importantly, I'd generally advise against using either of these. Instead of passing or returning a (reference to) a vector, you should normally work with an iterator (or two). In this case, you have a couple of perfectly reasonable choices -- you could use either a special iterator, or create a small algorithm. The iterator version would look something like this:
#ifndef GEN_SEQ_INCLUDED_
#define GEN_SEQ_INCLUDED_
#include <iterator>
template <class T>
class sequence : public std::iterator<std::forward_iterator_tag, T>
{
T val;
public:
sequence(T init) : val(init) {}
T operator *() { return val; }
sequence &operator++() { ++val; return *this; }
bool operator!=(sequence const &other) { return val != other.val; }
};
template <class T>
sequence<T> gen_seq(T const &val) {
return sequence<T>(val);
}
#endif
You'd use this something like this:
#include "gen_seq"
std::vector<int> vecInts(gen_seq(0), gen_seq(10));
Although it's open to argument that this (sort of) abuses the concept of iterators a bit, I still find it preferable on practical grounds -- it lets you create an initialized vector instead of creating an empty vector and then filling it later.
The algorithm alternative would look something like this:
template <class T, class OutIt>
class fill_seq_n(OutIt result, T num, T start = 0) {
for (T i = start; i != num-start; ++i) {
*result = i;
++result;
}
}
...and you'd use it something like this:
std::vector<int> vecInts;
fill_seq_n(std::back_inserter(vecInts), 10);
You can also use a function object with std::generate_n, but at least IMO, this generally ends up more trouble than it's worth.
As long as we're talking about things like that, I'd also replace this:
for(unsigned int ui = 0; ui < vecInts2.size(); ui++)
cout << vecInts2[ui] << endl;
...with something like this:
std::copy(vecInts2.begin(), vecInts2.end(),
std::ostream_iterator<int>(std::cout, "\n"));
In C++03 days, getIntVector() is recommended for most cases. In case of returnIntVector(), it might create some unncessary temporaries.
But by using return value optimization and swaptimization, most of them can be avoided. In era of C++11, the latter can be meaningful due to the move semantics.
In theory, the returnIntVector function returns the vector by value, so a copy will be made and it will be more time-consuming than the function which just populates an existing vector. More memory will also be used to store the copy, but only temporarily; since vecInts is locally scoped it will be stack-allocated and will be freed as soon as the returnIntVector returns. However, as others have pointed out, a modern compiler will optimize away these inefficiencies.
returnIntVector is more time consuming because it returns a copy of the vector, unless the vector implementation is realized with a single pointer in which case the performance is the same.
in general you should not rely on the implementation and use getIntVector instead.