How would one access an entire row of a multidimensional array?
For example:
int logic[4][9] = {
{0,1,8,8,8,8,8,1,1},
{1,0,1,1,8,8,8,1,1},
{8,1,0,1,8,8,8,8,1},
{8,1,1,0,1,1,8,8,1}
};
// I want everything in row 2. So I try...
int temp[9] = logic[2];
My attempt throws the error:
array initialization needs curly braces
I know I can retrieve the row using a FOR loop, however I'm curious if there was a more obvious solution.
That's not how arrays/pointers work in C++.
That array is stored somewhere in memory. In order to reference the same data, you'll want a pointer that points to the the beginning of the array:
int* temp = logic[2];
Or if you need a copy of that array, you'll have to allocate more space.
Statically:
int temp[9];
for (int i = 0; i < 9; i++) {
temp[i] = logic[2][i];
}
Dynamically:
// allocate
int* temp = new int(9);
for (int i = 0; i < 9; i++) {
temp[i] = logic[2][i];
}
// when you're done with it, deallocate
delete [] temp;
Or since you're using C++, if you want to not worry about all this memory stuff and pointers, then you should use std::vector<int> for dynamically sized arrays and std::array<int> for statically sized arrays.
#include <array>
using namespace std;
array<array<int, 9>, 4> logic = {
{0,1,8,8,8,8,8,1,1},
{1,0,1,1,8,8,8,1,1},
{8,1,0,1,8,8,8,8,1},
{8,1,1,0,1,1,8,8,1}
}};
array<int, 9> temp = logic[2];
As well as decaying the array to a pointer, you can also bind it to a reference:
int (&temp)[9] = logic[2];
One advantage of this is it will allow you to use it C++11 range-based for loops:
for (auto t : temp) {
// stuff
}
A direct assignment won't work. C++ does not allow that. At best you'll be able to assign them to point to the same data - int *temp = logic[2]. You'll need a for loop or something like the below.
I believe this would work:
int temp[9];
memcpy(temp, logic[2], sizeof(temp));
But I'd generally suggest using std::vector or std::array instead.
Related
I am fairly new to C++ and have been avoiding pointers. From what I've read online I cannot return an array but I can return a pointer to it. I made a small code to test it and was wondering if this was the normal / correct way to do this:
#include <iostream>
using namespace std;
int* test (int in[5]) {
int* out = in;
return out;
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int* pArr = test(arr);
for (int i = 0; i < 5; i++) cout<<pArr[i]<<endl;
cout<<endl;
return 0;
}
Edit: This seems to be no good. How should I rewrite it?
int* test (int a[5], int b[5]) {
int c[5];
for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
int* out = c;
return out;
}
Your code as it stands is correct but I am having a hard time figuring out how it could/would be used in a real world scenario. With that said, please be aware of a few caveats when returning pointers from functions:
When you create an array with syntax int arr[5];, it's allocated on the stack and is local to the function.
C++ allows you to return a pointer to this array, but it is undefined behavior to use the memory pointed to by this pointer outside of its local scope. Read this great answer using a real world analogy to get a much clear understanding than what I could ever explain.
You can still use the array outside the scope if you can guarantee that memory of the array has not be purged. In your case this is true when you pass arr to test().
If you want to pass around pointers to a dynamically allocated array without worrying about memory leaks, you should do some reading on std::unique_ptr/std::shared_ptr<>.
Edit - to answer the use-case of matrix multiplication
You have two options. The naive way is to use std::unique_ptr/std::shared_ptr<>. The Modern C++ way is to have a Matrix class where you overload operator * and you absolutely must use the new rvalue references if you want to avoid copying the result of the multiplication to get it out of the function. In addition to having your copy constructor, operator = and destructor, you also need to have move constructor and move assignment operator. Go through the questions and answers of this search to gain more insight on how to achieve this.
Edit 2 - answer to appended question
int* test (int a[5], int b[5]) {
int *c = new int[5];
for (int i = 0; i < 5; i++)
c[i] = a[i]+b[i];
return c;
}
If you are using this as int *res = test(a,b);, then sometime later in your code, you should call delete []res to free the memory allocated in the test() function. You see now the problem is it is extremely hard to manually keep track of when to make the call to delete. Hence the approaches on how to deal with it where outlined in the answer.
Your code is OK. Note though that if you return a pointer to an array, and that array goes out of scope, you should not use that pointer anymore. Example:
int* test (void)
{
int out[5];
return out;
}
The above will never work, because out does not exist anymore when test() returns. The returned pointer must not be used anymore. If you do use it, you will be reading/writing to memory you shouldn't.
In your original code, the arr array goes out of scope when main() returns. Obviously that's no problem, since returning from main() also means that your program is terminating.
If you want something that will stick around and cannot go out of scope, you should allocate it with new:
int* test (void)
{
int* out = new int[5];
return out;
}
The returned pointer will always be valid. Remember do delete it again when you're done with it though, using delete[]:
int* array = test();
// ...
// Done with the array.
delete[] array;
Deleting it is the only way to reclaim the memory it uses.
New answer to new question:
You cannot return pointer to automatic variable (int c[5]) from the function. Automatic variable ends its lifetime with return enclosing block (function in this case) - so you are returning pointer to not existing array.
Either make your variable dynamic:
int* test (int a[5], int b[5]) {
int* c = new int[5];
for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
return c;
}
Or change your implementation to use std::array:
std::array<int,5> test (const std::array<int,5>& a, const std::array<int,5>& b)
{
std::array<int,5> c;
for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
return c;
}
In case your compiler does not provide std::array you can replace it with simple struct containing an array:
struct array_int_5 {
int data[5];
int& operator [](int i) { return data[i]; }
int operator const [](int i) { return data[i]; }
};
Old answer to old question:
Your code is correct, and ... hmm, well, ... useless. Since arrays can be assigned to pointers without extra function (note that you are already using this in your function):
int arr[5] = {1, 2, 3, 4, 5};
//int* pArr = test(arr);
int* pArr = arr;
Morever signature of your function:
int* test (int in[5])
Is equivalent to:
int* test (int* in)
So you see it makes no sense.
However this signature takes an array, not pointer:
int* test (int (&in)[5])
A variable referencing an array is basically a pointer to its first element, so yes, you can legitimately return a pointer to an array, because thery're essentially the same thing. Check this out yourself:
#include <assert.h>
int main() {
int a[] = {1, 2, 3, 4, 5};
int* pArr = a;
int* pFirstElem = &(a[0]);
assert(a == pArr);
assert(a == pFirstElem);
return 0;
}
This also means that passing an array to a function should be done via pointer (and not via int in[5]), and possibly along with the length of the array:
int* test(int* in, int len) {
int* out = in;
return out;
}
That said, you're right that using pointers (without fully understanding them) is pretty dangerous. For example, referencing an array that was allocated on the stack and went out of scope yields undefined behavior:
#include <iostream>
using namespace std;
int main() {
int* pArr = 0;
{
int a[] = {1, 2, 3, 4, 5};
pArr = a; // or test(a) if you wish
}
// a[] went out of scope here, but pArr holds a pointer to it
// all bets are off, this can output "1", output 1st chapter
// of "Romeo and Juliet", crash the program or destroy the
// universe
cout << pArr[0] << endl; // WRONG!
return 0;
}
So if you don't feel competent enough, just use std::vector.
[answer to the updated question]
The correct way to write your test function is either this:
void test(int* a, int* b, int* c, int len) {
for (int i = 0; i < len; ++i) c[i] = a[i] + b[i];
}
...
int main() {
int a[5] = {...}, b[5] = {...}, c[5] = {};
test(a, b, c, 5);
// c now holds the result
}
Or this (using std::vector):
#include <vector>
vector<int> test(const vector<int>& a, const vector<int>& b) {
vector<int> result(a.size());
for (int i = 0; i < a.size(); ++i) {
result[i] = a[i] + b[i];
}
return result; // copy will be elided
}
In a real app, the way you returned the array is called using an out parameter. Of course you don't actually have to return a pointer to the array, because the caller already has it, you just need to fill in the array. It's also common to pass another argument specifying the size of the array so as to not overflow it.
Using an out parameter has the disadvantage that the caller may not know how large the array needs to be to store the result. In that case, you can return a std::vector or similar array class instance.
Your code (which looks ok) doesn't return a pointer to an array. It returns a pointer to the first element of an array.
In fact that's usually what you want to do. Most manipulation of arrays are done via pointers to individual elements, not via pointers to the array as a whole.
You can define a pointer to an array, for example this:
double (*p)[42];
defines p as a pointer to a 42-element array of doubles. A big problem with that is that you have to specify the number of elements in the array as part of the type -- and that number has to be a compile-time constant. Most programs that deal with arrays need to deal with arrays of varying sizes; a given array's size won't vary after it's been created, but its initial size isn't necessarily known at compile time, and different array objects can have different sizes.
A pointer to the first element of an array lets you use either pointer arithmetic or the indexing operator [] to traverse the elements of the array. But the pointer doesn't tell you how many elements the array has; you generally have to keep track of that yourself.
If a function needs to create an array and return a pointer to its first element, you have to manage the storage for that array yourself, in one of several ways. You can have the caller pass in a pointer to (the first element of) an array object, probably along with another argument specifying its size -- which means the caller has to know how big the array needs to be. Or the function can return a pointer to (the first element of) a static array defined inside the function -- which means the size of the array is fixed, and the same array will be clobbered by a second call to the function. Or the function can allocate the array on the heap -- which makes the caller responsible for deallocating it later.
Everything I've written so far is common to C and C++, and in fact it's much more in the style of C than C++. Section 6 of the comp.lang.c FAQ discusses the behavior of arrays and pointers in C.
But if you're writing in C++, you're probably better off using C++ idioms. For example, the C++ standard library provides a number of headers defining container classes such as <vector> and <array>, which will take care of most of this stuff for you. Unless you have a particular reason to use raw arrays and pointers, you're probably better off just using C++ containers instead.
EDIT : I think you edited your question as I was typing this answer. The new code at the end of your question is, as you observer, no good; it returns a pointer to an object that ceases to exist as soon as the function returns. I think I've covered the alternatives.
you can (sort of) return an array
instead of
int m1[5] = {1, 2, 3, 4, 5};
int m2[5] = {6, 7, 8, 9, 10};
int* m3 = test(m1, m2);
write
struct mystruct
{
int arr[5];
};
int m1[5] = {1, 2, 3, 4, 5};
int m2[5] = {6, 7, 8, 9, 10};
mystruct m3 = test(m1,m2);
where test looks like
struct mystruct test(int m1[5], int m2[5])
{
struct mystruct s;
for (int i = 0; i < 5; ++i ) s.arr[i]=m1[i]+m2[i];
return s;
}
not very efficient since one is copying it delivers a copy of the array
I'm trying to make a dynamic 2-dimensional array.
Here is my code:
bool b_alloc_table_2_dim(int ***piTable, int iSizeX, int iSizeY)
{
*piTable = new int*[iSizeX];
for (int ii = 0; ii < iSizeX; ii++)
*piTable[ii] = new int[iSizeY]; // here i get the exception
return true;
}
int main()
{
int **x ;
b_alloc_table_2_dim( &x, 3, 5);
return 0;
}
I can't find anything wrong with the code. After calling my function x is supposed to point to the 2d array.
The [] operator takes precedence over *. cppreference
So the line
*piTable[ii] = new int[iSizeY];
is equivalent to
*(piTable[ii]) = new int[iSizeY];
what you wanted to write is:
(*piTable)[ii] = new int[iSizeY];
Use an actual container
Using an actual container avoids a lot of the types of issues that you have encountered.
Instead of
int**
For a 2d array (a matrix) a more suitable data structure could be
std::array< std::array<int, cols>, rows>
if the sizes is known at compile time.
If not, it's probably best to just use a single vector ala.
auto my_array2d = std::vector<int>(rows*cols);//array now has 'rows*cols' elements of '0'
and handle indexing yourself.
The best thing is of course to use a library like perhaps eigen or boost
I want to declare multi dimensional (int his case two-dimensional) array. I can't declare size of global array. With one dimension, everything works:
#include <iostream>
#include <fstream>
using namespace std;
int N, M;
bool *table;
int main()
{
ifstream in ("in.txt");
in >> N >> M;
table = new bool[N];
return 0;
}
But if i want to declare two-dimensional array, I get an error:
'M' cannot appear in a constant-expression
#include <iostream>
#include <fstream>
using namespace std;
int N, M;
bool **table;
int main()
{
ifstream in ("in.txt");
in >> N >> M;
table = new bool[N][M];
return 0;
}
What is my option apart from declaring number instead of N and M, creating vector array or declaring table in main function?
What is my option apart from declaring number instead of N and M, creating vector array or declaring table in main function?
Allocate memory for N pointers.
For each pointer, allocate memory for M elements of type bool.
table = new bool*[N];
for (int i = 0; i < N; ++i )
{
table[i] = new bool[M];
}
When it's time to deallocate, use:
for (int i = 0; i < N; ++i )
{
delete [] table[i];
}
delete [] table;
You can avoid all the hassles of memory allocation and deallocation by using std::vector.
std::vector<std::vector<bool>> table(N, std::vector<bool>(M));
Use the old way of doing things: allocate a unidimensional array and afterwards access it by the unique index by doing the calculation (i*N+j). If you want to hide it create a function with two parameters for that.
If you want to avoid all the hassle of true multi-level arrays, you could:
int N=2, M=3;
bool *table = new bool[N*M];
// to access the element at (n,m):
ele = table[n*M + m];
This makes all the allocation/deallocation dead simple with the slight cost of having to type a bit more when accessing the elements. You could use a macro to fix that, of course.
i am new to c++ and i am trying to create an Array from within a function with just the array size, [row][col], as the argument. I know you cannot return an array from a function in c++. I would allocate memory in these situations if i were to code in C. However, i am not sure what is the C++ way (:
I tried,
int** get2Darray(int row, int col){
int** randInts = new int[row][col]; //Invalid. Constant required.
return randInts;
}
Thanks.
EDIT: vector class does the trick, however, my program is heavily modular. I dont have access to the main program. My function should be called and a fresh array should be created and returned. Implementation should only be done inside this function
Either change int** randInts = new int[row][col]; into int* randInts = new int[row * col]; or define int** randInts as follows:
int** randInts = new int*[row];
for (int i = 0; i < row; ++i) {
randInts[i] = new int[col];
}
It's a C way, not a C++ way. In C++ you should use containers (e.g. a vector as suggested in the comments).
I have shown this using vector <vector<T> >, but you can also use Eigen matrix or boost::ublas::matrix
std::vector< std::vector<int> > foo(const int rows, const int cols)
{
std::vector< std::vector<int> > v;
v.resize(rows);
for (auto i = 0; i < rows; i++)
{
v[i].resize(cols);
}
return v;
}
This will return a matrix of desired dimensions, and all elements will be initialized to 0.
The std::move part invokes a behavior called move semantics. You can read up on it. It's basically a better way of returning objects across a function boundary.
For compatibility's sake, if you must have a native array, then do this :
std::vector< vector<int> > temp = foo(rows, cols);
int *v = &temp[0][0];
Now, you can implement the gymnastics to get the correct index inside of int *v. You don't need multiple indirection.
P.S. This implementation assumes that your compiler supports C++ 11.
I'm brand new to C++ and am having trouble trying to get a function (which takes an array) to return an array. The function is a very basic sorting algorithm for an array of integers of size 4. What i have is below:
int[] sortArrayAscending(int arrayToSort[3]) {
int sortedArray[3];
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
I think i'm getting really confused with the syntax i need to use (the function calls to min, lower, higher, max all work fine.
I would really appreciate some help.
Thank you
EDIT2: Thank you for all the comments. I have now solved it thanks to #Rook's and #Bob Yoplait's answers. The code is used is:
int* sortArrayAscending(int arrayToSort[4], int sortedArray[4]) {
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
int _tmain(int argc, _TCHAR* argv[])
{
int testNumbers[4] = {8,14,1,27};
int testSorted[4];
sortArrayAscending(testNumbers,testSorted);
for (int i = 0; i < 4; i++) {
cout << testSorted[i] << endl;
}
system("pause");
return 0;
}
Thank you for all your help - now time to lookup vectors!
PS I appreciate #Luchian Grigore's solution is most likely the best practise way of doing things, but that wasn't specifically my question
Me, I'd probably use std::array<int, 4> if I was using a modern C++ compiler. Deals nicely with bounds checking and memory management and returning from/passing into functions. You can also use existing STL sort mechanisms and functions upon it; no need to reinvent the wheel!
Now, in your case,
int sortedArray[3];
is a local variable and you should never return a reference to it directly. You could do something like :
int* sortedArray = new int[4];
// do stuff
return sortedArray;
(also note the size of the array, 4, not 3 in your case!) but in this case you have to remember to delete the array at some point in the future or your application will leak memory.
You can also pass in the array by reference, using an approach like
void sort_array(std::array<int, 4>& the_array);
or
void sort_array(int** the_array)
and in these cases you can modify the array in place, or copy the answer into the argument when you're done sorting.
EDIT: After your edit, you, your function returns a pointer to an array. Should work.
You can either return a pointer or a std::vector.
Note that in your code, you'd be running into undefined behavior, because sortedArray goes out of scope at the end of the method, and the memory is freed.
I'd do this instead:
std::vector<int> sortArrayAscending(int arrayToSort[4]) {
std::vector<int> sortedArray(4);
sortedArray.push_back( minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
return sortedArray;
}
Actually, I wouldn't. I'd just use std::sort instead of creating my own function, but that's just me.
As this is C++, suggest using a std::vector<int> instead:
std::vector<int> sortArrayAscending(int arrayToSort[3]) {
std::vector<int> sortedArray(4); // Note 4, not 3.
sortedArray[0] = ...;
sortedArray[1] = ...;
sortedArray[2] = ...;
sortedArray[3] = ...;
return sortedArray;
}
Note there are several algorithms already available that will perform some of the tasks that you appear to be performing:
max_element()
min_element()
You are returning pointer to local variable, which leads to undefined behavior. sortedArray is statically allocated array with automatic storage duration, which means that memory where it resides is being freed once you leave the scope of the function.
You should allocate it dynamically by using new[] or even better: use std::vector instead. If you choose to allocate it by using new[], don't forget to free it by calling delete[] when you don't need this memory anymore.
Also note that int sortedArray[3]; declares an array of size of 3 elements indexed from 0 to 2. If you access 4th element of the array whose size is 3 (if you access the memory "past the last element of the array object"), the behavior is undefined as well.
Use Boost::Array (or std::array in C+11) that provides proper value semantic to C array.
boost::array<int,4> sortArrayAscending(boost::array<int,4>7 arrayToSort)
{
boost::array<int,4> sortedArray;
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
It is not like in Java
Either you pass sortedArray as a parameter to the func
int* sortArrayAscending(int* arrayToSort, int* sortedArray) {
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
void toto() {
int array[4]; // and fill values...
int sortedArray[4];
sortArrayAscending(array, sortedArray);
}
or
int* sortArrayAscending(int* arrayToSort) {
int* sortedArray = new int[4];
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
and then you need to delete the returned array in the second case.
Arrays are always passed by reference to any function in C++.
So, just pass your array to the function. Your original array would get sorted and you can then use it in your program. I believe there is no need to return the array explicitly.