I think it is a trivial question, but I couldn't find a specific solution to it. I'm trying to append array into a vector, using push_back() function. Here is the code:
int main()
{
std::vector<int*> matchVector;
int msmTemp[3];
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
matchVector.push_back(msmTemp);
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
matchVector.push_back(msmTemp);
for(auto i : matchVector)
{
for(int j = 0; j<3; j++)
{
cout<<i[j]<<", ";
}
cout<<"\n";
}
return 0;
}
The output I'm getting is 4,7,0 two times. I don't understand as to why I'm not able to see the previous values, namely 1,2,3? Is it because of the type of vector matchVector defined above? I think it needs to be array only.
A int* is a pointer to an integer.
An int[3] is an array of 3 integers.
An array of 3 integers "decays" at the drop of a hat to a pointer to the first element.
When you do push_back(msmTemp), you push a pointer to the first element of msmTemp into the vector.
Pointers in C++ do not own what they point to. The vector afte the two push_backs contains two pointers, both to the same array msmTemp.
When you later iterate over the vector, you get two pointers in turn. Each points to msmTemp.
You then use [] to index those pointers. When you have a pointer to the first element of an array, you can use [] to access the other elements of the array. [0] is the first element, [1] the second, etc.
So you look at the 3 elements in msmTemp (luckily it has 3) and look at them twice, because you have two pointers into it in the vector.
You can inject elements like this:
std::vector<int> matchVector;
int msmTemp[3];
msmTemp[0]={1};
msmTemp[1]={2};
msmTemp[2]={3};
matchVector.insert( matchVector.end(), std::begin(msmTemp), std::end(msmTemp) );
etc. This ends up with a vector containing 6 elements, not two arrays.
If you want arrays as values you need std::array:
std::vector< std::array<int,3> > matchVector;
std::array<int, 3> msmTemp;
and then your code works as written. std::array is a library type that acts sort of like a raw array, but it doesn't have the decay-to-pointer problems of a raw array.
Forget that int[3] names a type. C arrays don't behave like sensible values. Arrays are named std::array<type, count>.
#include <vector>
#include <array>
int main()
{
std::vector<std::array<int, 3>> matchVector;
std::array<int, 3> msmTemp;
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
matchVector.push_back(msmTemp);
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
matchVector.push_back(msmTemp);
for(auto & arr : matchVector)
{
for(auto i : arr)
{
std::cout << i <<", ";
}
std::cout<<"\n";
}
return 0;
}
The other answers already explain how to fix your code. I think it's also good to explain why your code behaves the way it does:
Here you tell your compiler to create an std::vector that holds pointers to int:
std::vector<int*> matchVector;
Here you tell your compiler to allocate some space on the stack that fits 3 ints:
int msmTemp[3];
Here you tell your compiler to write the values 1, 2 and 3 into the memory previously allocated:
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
Here you tell your compiler to take the address of that allocated space, treat it as a pointer and pass it to push_back. This is called array decaying:
matchVector.push_back(msmTemp);
Your matchVector now contains 1 element, which is a pointer to the address of the memory on your stack that was allocated to hold 3 ints.
Here you tell your compiler to write the values 4, 7 and 0 in the memory previously allocated. Note that this is still the same memory block as before:
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
Here you tell your compiler to again take the address of the allocated space, treat it as a pointer and pass it to push_back:
matchVector.push_back(msmTemp);
Thus matchVector now contains 2 identical values, each a pointer to the same memory location. Specifically the memory location that you last wrote 4, 7 and 0 into.
Related
I have the following piece of code, which is only half on the entire code:
// Declare map elements using an enumeration
enum entity_labels {
EMPTY = 0,
WALL
};
typedef entity_labels ENTITY;
// Define an array of ASCII codes to use for visualising the map
const int TOKEN[2] = {
32, // EMPTY
178 // WALL
};
// create type aliases for console and map array buffers
using GUI_BUFFER = CHAR_INFO[MAP_HEIGHT][MAP_WIDTH];
using MAP_BUFFER = ENTITY[MAP_HEIGHT][MAP_WIDTH];
//Declare application subroutines
void InitConsole(unsigned int, unsigned int);
void ClearConsole(HANDLE hStdOut);
WORD GetKey();
void DrawMap(MAP_BUFFER & rMap);
/**************************************************************************
* Initialise the standard output console
*/
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != INVALID_HANDLE_VALUE)
{
ClearConsole(hStdOut);
// Set window title
SetConsoleTitle(TEXT("Tile Map Demo"));
// Set window size
SMALL_RECT srWindowRect;
srWindowRect.Left = 0;
srWindowRect.Top = 0;
srWindowRect.Bottom = srWindowRect.Top + MAP_HEIGHT;
srWindowRect.Right = srWindowRect.Left + MAP_WIDTH;
SetConsoleWindowInfo(hStdOut, true, &srWindowRect);
// Set screen buffer size
COORD cWindowSize = { MAP_WIDTH, MAP_HEIGHT };
SetConsoleScreenBufferSize(hStdOut, cWindowSize);
}
/*************************************************************************/
/*************************************************************************
* Initialise the tile map with appropriate ENTITY values
*/
MAP_BUFFER tileMap;
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
tileMap [row][col] = WALL;
}
}
Essentially the entire code is used to create a tile map and output it to screen but I'm attempting to make tileMap a dynamic array in runtime.
I have tried creating one down where the tileMap is being created.
I've tried creating one just after "entity_lables" are given the typedef "ENTITY".
I've tried creating one after the "MAP_BUFFER" and "GUI_BUFFER" become aliases.
But still I'm at a loss, I have no idea on how to successfully implement a dynamic array to tileMap, and I certainly don't know the best spot to put it.
Any help would be greatly appreciated.
The syntax you are using for defining your array is for a constant sized C array. In general you should shy away from C arrays unless the size of the data is determined at compile time(and never needs to change) and the array never leaves the scope(because a C array does not retain information on its own size.)
In place of constant or dynamically sized C arrays I would suggest to use the Vector container. The Vector is a dynamically sized container that fills up from the back, the last element you have added to
std::vector<std::vector<ENTITY>>
To add the vector container to your project add the line
#include <vector>
To fill the container your loop could look like:
MAP_BUFFER tileMap;
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
std::vector<ENTITY> column; // A column of the tile map
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
column.push_back(WALL); // Add one element to the column
}
tileMap.push_back(column); // Add the column to the tile map
}
or you could initialize the Vector to the size you want at the beginning and use your current loop to assign the tile values:
using TILE_MAP = vector<vector<ENTITY>>;
// MAP_WIDTH x MAP_HEIGHT multidimensional vector
TILE_MAP tileMap(MAP_WIDTH, vector<ENTITY>(MAP_HEIGHT));
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
tileMap [row][col] = WALL;
}
}
Calling an element of a vector after it has been filled has the same syntax as an array.
tileMap[2][4]
You can also check the length of the vector:
int rows = tileMap.size();
if( rows > 0 )
int columnsInRow0 = tileMap[0].size()
While you are at it you should look into other containers like Maps and Sets since they make your life easier.
Edit:
Since you want to know how to make a dynamic array not using a vector I will give you an answer: std::vector is the C++ defined dynamically sized array. C arrays will not change size after they are defined, vector will.
However I think you are asking about the ability to define runtime constant sized arrays. So I will explain what they are and why you should not use them.
When you define the C array you are probably getting a warning saying that the expression needs to be constant.
A C array is a pointer to the stack. And the implementation of the compiletime C array is that it needs to be a constant size at compile time.
int compiletimeArray[] = { 1, 2, 3 };
// turns out c arrays are pointers
int* ptr = compiletimeArray;
// prints 2
std::cout << compiletimeArray[1];
// prints 2
std::cout << ptr[1];
// prints 2
std::cout << *(compiletimeArray + 1);
// also prints 2
std::cout << *(ptr + 1); //move pointer 1 element and de-reference
Pointers are like a whiteboard with a telephone number written on it. The same kind of issues occur as with telephone numbers; number on whiteboard has been erased, number on whiteboard has changed, recipient does not exist, recipient changed their number, service provider running out of available numbers to give new users... Keep that in mind.
To get create a runtime constant sized array you need to allocate the array on the heap and assign it to a pointer.
int size = 4;
int* runtimeArray = new int[size]; // this will work
delete[] runtimeArray; // de-allocate
size = 8; // change size
runtimeArray = new int[size]; // allocate a new array
The main difference between the stack and heap is that the stack will de-allocate the memory used by a variable when the program exits the scope the variable was declared in, on the other hand anything declared on the heap will still remain in memory and has to be explicitly de-allocated or you will get a memory leak.
// You must call this when you are never going to use the data at the memory address again
// release the memory from the heap
delete[] runtimeArray; // akin to releasing a phone number to be used by someone else
If you do not release memory from the heap eventually you will run out.
// Try running this
void crashingFunction() {
while(true)
{
// every time new[] is called ptr is assigned a new address, the memory at the old address is not freed
// 90001 ints worth of space(generally 32 or 64 bytes each int) is reserved on the heap
int* ptr = new int[90001]; // new[] eventually crashes because your system runs out of memory space to give
}
}
void okFunction() {
// Try running this
while(true)
{
// every time new[] is called ptr is assigned a new address, the old is not freed
// 90001 ints worth of space is reserved on the heap
int* ptr = new int[90001]; // never crashes
delete[] ptr; // reserved space above is de-allocated
}
}
Why use std::vector? Because std::vector internally manages the runtime array.
// allocates for you
vector(int size) {
// ...
runtimeArray = new runtimeArray[size];
}
// When the vector exits scope the deconstructor is called and it deletes allocated memory
// So you do not have to remember to do it yourself
~vector() {
// ...
delete[] runtimeArray;
}
So if you had the same scenario as last time
void vectorTestFunction() {
// Try running this
while(true)
{
std::vector<int> vec(9001); // internally allocates memory
} // <-- deallocates memory here because ~vector is called
}
If you want to use a runtime constant array I suggest the std:array container. It is like vector in that it manages its internal memory but is optimized for if you never need to add new elements. It is declared just like vector but does not contain resizing functions after its constructor.
#include <iostream>
using namespace std;
int main()
{
int *array1 = new int [5]();
int *array2 = new int [7]();
array1[2] = 3;// or anychange
array2[2] = 3;// to both arrays
if (array1==array2)
{
//if all values of the both arrays are equal
}
else
{
//if all values of the both arrays are not equal
}
return 0;
}
I have two dynamically allocated array using new (the size may or may not be same). Now I want to compare all elements of array (if size and elements are same, then true, if not either of these then false).
How to do in C++? (not interested using vector in my problem scenario)
First off, I would like to encourage you to use std::vector for dynamically allocated arrays. They will free the allocated memory safely and automatically and you can always retrieve their size without extra manual book-keeping.
Once you have that, you can compare the two arrays in the following way:
#include <vector>
int main()
{
std::vector<int> v1 = { 1, 2, 3 };
std::vector<int> v2 = { 1, 2, 3, 4 };
const bool theyAreEqual = v1 == v2;
}
Comparing two pointers as you did, only compares the addresses of the first elements and not the sizes and the contents of the dynamic arrays elementwise. That's one of the reasons, that it's much safer to use std::vector instead of C-style arrays.
array1 == array2 compares pointers. They will never be equal. Furthermore, you can't know how many elements is in a dynamically allocated array, unless you're:
having its size stored separately
using sentinel value to determine its end - you choose a value (e.g. -1) to represent end of the array (like c-style strings usually use \0)
Then you'll be able to know how many elements to iterate over, comparing the elements of both arrays.
Here is a way to resolve it, but I highly recommend vectors, in cases like this.
You need the length and a bool for checking. check is true for default and arrays should be allocated with length1 and length2.
//...
if (length1 != length2) check = false;
else for (int i = 0; i < length1; i++)
{
if (array1[i] != array2[i])
{
check = false;
break;
}
}
if (check)
//...
I followed up on Ralph comment, because I also wanted to see what std::equal did, and the == operator of std::vector does the right thing, and surprisingly simpler to use than the std::equal operator. If you use the latter, you will need to make sure to user begin()/end() for both arrays (It is a C++14 version of std::equal), or add v1.size() == v2.size() &&...
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v1 = { 1, 2, 3 };
std::vector<int> v2 = { 1, 2, 3, 4 };
std::vector<int> v3 = { 1, 2, 3 };
const bool theyAreEqualv1v2 = v1 == v2;
const bool theyAreEqualv1v3 = v1 == v3;
const bool theyAreEqualStdv1v2 = std::equal(v1.begin(),v1.end(), v2.begin(),v2.end());
const bool theyAreEqualStdv1v2bad = std::equal(v1.begin(),v1.end(), v2.begin());
const bool theyAreEqualStdv1v3 = std::equal(v1.begin(),v1.end(), v3.begin(),v3.end());
// std::equal according to http://en.cppreference.com/w/cpp/algorithm/equal actually
// only compares the first range thus you would really need begin()/end() for both arrays
printf("equal v1v2: %d\n",theyAreEqualv1v2);
printf("equal v1v3: %d\n",theyAreEqualv1v3);
printf("std::equal v1v2: %d\n",theyAreEqualStdv1v2);
printf("std::equal v1v2 bad: %d\n",theyAreEqualStdv1v2bad);
printf("std::equal v1v3: %d\n",theyAreEqualStdv1v3);
return 0;
}
clang++ -std=c++14 -stdlib=libc++ c.cpp
output:
equal v1v2: 0
equal v1v3: 1
std::equal v1v2: 0
std::equal v1v2 bad: 1
std::equal v1v3: 1
so I'm having an issue passing an entire array of histograms into a function in C++
the arrays are declared like this
TH1F *h_Energy[2];
h_Energy[0] = new TH1F("h1", "h1", 100, 0, 100);
h_Energy[1] = new TH1F("h2", "h2", 100, 0, 100);
And here is what I'm trying to do in the function:
void overlayhists(TH1 *hists, int numhists) {
int ymax = 0;
for (int i=0; i<numhists; i++) {
if (hist[i].GetMaximum() > ymax) {
ymax = (hist[i].GetMaximum())*1.05;
}
}
}
And I'm passing the function an array like this
overlayhists(*h_Energy, 2);
Where h_Energy is an 1D array with 2 elements. The code will run through the first histogram in the loop but as soon as it starts the second loop and tries to access hist[i].GetMaximum() on the second try it segfaults.
What gives?
This creates an array of pointers to type TH1F
TH1F *h_Energy[2]; //edited after OP changed
If you want to use this, and subsequently pass it as an argument
You must first initialize it, and then create your function prototype to accommodate:
void overlayhists(TH1F **hists, int numhists);
^^
From what you have shown above, you would call it like this: (after your initializations)
h_Energy[0] = new TH1F("h1", "h1", 100, 0, 100);
h_Energy[1] = new TH1F("h2", "h2", 100, 0, 100);
overlayhists(h_Energy, 2);
1. Passing any array to function in c++ to change the content:
Refer to this code snippet:
//calling:
int nArr[5] = {1,2,3,4,5};
Mul(nArr, 5);
Whenever you pass an array to function you actually pass the pointer to first element of the array. This is implicit to C++ and C. If you pass normal value(non array) it will be considered as pass by value though.
// Function Mul() declaration and definition
void MUl(int* nArr, size_t nArrSize){
size_t itr = 0;
for(;itr<nArrSize; itr++)
nArr[i] = 5*nArr;// here we've coded to multiply each element with 5
}
2. Passing any Ptr to function in c++ to change what pointer is pointing to:
Now let us suppose we want to copy nArr (from above code snippet) to another array, say nArrB
The best way for a beginner would be to use reference to the pointer.
You can pass reference to the pointer to your function
//so we had
int nArr[5] = {1,2,3,4,5};
int *nArrB;
Here we don't know the gonnabe size of nArrB.
to copy nArr to nArrB we have to pass nArr, address of pointer to nArrB(or reference to pointer of nArrB or pointer to pointer of nArrB) and size of array.
Here is the implementation.
//Calling
CopyNArr(nArr, &nArrB, 5);
//Function implementation
void CopyNArr(int* nArr, int* & nArrB, size_t nArrSize) {
// dymanically allocating memory size for array. Assuming 4 byte int size
nArrB = new int[nArrSize*4];
size_t itr = 0;
//Copying values
for(;itr<nArrSize; itr++)
nArrB[i] = nArr[i];
}
//After copy nArrB is pointing to first element of 5 element array.
I hope it helped. Write for any further clarification.
You have an array of size 2, but you've created only one element. And that one with a wrong index. Array indexing starts with 0.
The elements should be at h_histogram[0] and h_histogram[1].
I am sorry if this answer is completely irrelevant but
I am tempted to post it. These is an experiment I have
done after seeing your question.
#include<iostream>
using namespace std;
main()
{
int e[2]={0,1};
int *p[2];
int i;
/*
Printing the array e content using one pointer
from an array of pointers. Here I am not using p[2]
at all.
*/
p[1]=e;
cout<<"Elements of e are : \n";
for(i=0;i<2;i++)
{
cout<<*(p[1]+i)<<endl;
/*
In the above line both *((*p)+i) and *(p+i)
won't serve the purpose of printing the array values.
*/
}
/*Printing the array e content using pointer to array*/
cout<<"Elements of e are : \n";
for(i=0;i<2;i++)
{
cout<<*(e+i)<<endl;
}
/*Note that pointer to array is legal but array TO pointer
(don't confuse with array OF pointers) is not.*/
}
Hope this will refresh your understanding.
I am writing a program to simulate a cache in c++ and am trying to copy addresses that are given in a file into an array. I am struggling to figure out how to copy an array into another array so that I can have an array of memory address arrays. I have read in the addresses into an array called "address" and I want my simulated cache to be an array called "L1_Cache". h is a counter that I am incrementing after I put an address into the L1_Cache. Also, cache size is going to be how many lines of addresses are available in my L1_Cache array, which will be decided by the user of the program. Below is the snippet where I am trying to put the array into the other array.
if(sizeof(L1_Cache) < cachesize)
strcpy(L1_Cache[][h], address);
they are defined as:
const char* address[10];
char* L1_Cache;
If anyone has any suggestions on how to copy one array into another array to make an array of arrays, let me know. I am not sure if anything I am doing is correct, but I am struggling to figure this out.
I want to compare new addresses that I am given to old addresses that are already in the L1_Cache array.
Yes, it is possible to make an array of arrays.
int a[3][3]; // a is an array of integer arrays
You have
a[0]; // this refers to the first integer array
a[1]; // this refers to the second array
Is the following what you are looking for?
#include <iostream>
#include <cstring>
int main()
{
char p[2][256];
strncpy(p[0], "This is my first address", 256);
strncpy(p[1], "This is my second address", 256);
std::cout << p[0] << std::endl << p[1];
return 0;
}
Yes. They are called multidimensional arrays.
They can have any number of dimensions.
For example:
int foo[3][3]; // initialize the 2 dimensional array of integers
foo[0][0] = 1; // change a value
foo[0][1] = 2; // change a value
foo[0][2] = 3; // change a value
foo[1][0] = 4; // change a value
foo[1][1] = 5; // change a value
foo[1][2] = 6; // change a value
foo[2][0] = 7; // change a value
foo[2][1] = 8; // change a value
foo[2][2] = 9; // change a value
for(int i=0;i<3;++i){ // display the 2d array
for(int j=0;j<3;++j){
cout<<foo[i][j];
}
cout<<endl;
}
What's happening:
Values are being assigned in a chart.
Think of it like writing a value on each point of a piece of paper.
OK here's what I am trying. I have passed an array to a function. And while returning I want to send in only those values which are defined in a array. For example, say I have an array definition of 10, I want to return only 5 values from that array, in the function.
Any suggestions!? Thanks.
Sample Code:
sc_uint<8> *arrayfill(struct){
sc_uint<8> array[10];
array[1] = struct.a;
array[2] = struct.b;
...
if (struct.trigger == false){
array[10] =0;
}
else
{
array[10] = struct.j;
}
return array;
}
So now here is the thing, I want to return only upto 9 values of array when struct.trigger is false, else I am returning all the values of array. And this is where I am unable to find a solution.
I think you can just use the array reference as the in and out parameters, and extract 5 elements from the in array, and then put it into the out array.
Like:
void ExtrctElemnts(const std::vector<int>& in_array, std::vector<int>& out_array){
for(int i = 0; i < 5; i++){
out_array.push_back(in_array.at(i));
}
}
Of course, you can also choose specific elements of the in array.