I want to define dynamic array h of size size and later in other functions, modify and use it as here:
class definition:
static int size=10;
class hash{
public:
string h[size];
hash();
void resize();
void operations();
void print();
};
hash::hash()
{
h[size-1]="nikhil"; //size=10 now.
}
/*Defining `h` as `string* h=new string[size];` is not working.
My compiler (MinGW on Windows 7) show error: dynamic allocation is not allowed by default*/
// resizing the array
void hash::resize( )
{
string temp[2*size];
for(int i=0;i<=size;i=i+1)
{
temp[i]=h[i];
}
size=2*size;
h=temp;
}
void hash::print()
{
for(int i=0;i<size;i=i+1)
{if(!h[i].empty())
{cout<<"h["<<i<<"]="<<h[i]<<endl;}
}
}
int main()
{
hash p;
p.resize();//now size should change to 20.
p.print();
}
Where is the problem is it defining the size variable or in resizing the array?
Use std::vector if you need arrays of dynamic size.
class hash {
public:
std::vector<std::string> h;
hash();
void resize();
void operations();
void print();
};
hash::hash() : h(10) {
h[9] = "nikhil";
}
void hash::resize() {
h.resize(2 * h.size());
}
Though note that std::vector does resizing for you automatically if you add new elements using push_back. Also note that the standard library has hash table data types already (std::unordered_set and std::unordered_map), so you don’t have to write them yourself.
I do not know C++ but you haven't exactly told what is going on.
But the way your resize() method is working is the for loop goes through 2*the size of H which will cause a problem.
When you loop through 2*size it is trying to loop through more items than what you actually have in the original array. you have to loop through the original array size.
for(int i = 0; i < h.size(); i++)
{
temp[i] = h[i];
}
I can barely see the comments in your code they are too light for me so I didn't see them.
But to explain a little better i guess, lets say original array is size 5 your new one is size 10 when you loop through 10 items you dont have 10 items in the original array so you'll get errors when trying to access them.
Related
As a C++ beginner, I oftentimes find myself struggling with the declaration of class attributes inside the header file that need more information than just a name, like arrays and objects of other classes with constructors.
Here's an example
SomeClass.h :
#include "OtherClass.h"
class SomeClass {
int num; // works fine
float arr[]; // produces an error because size is not declared
OtherClass obj; // produces an error because the constructor parameters are not passed in
public:
void setup();
void update();
};
SomeClass.cpp:
#include "SomeClass.h"
void SomeClass::setup() {
num = 10; // easy peasy, works!
arr = float some_arr[5 * num]; // error
// Fill in the array
for (int i = 0; i < 5 * num; i += num) {
ass[i] = 12;
}
// Fill in the class attributes
obj = {120, 40}; // error
}
void SomeClass::update() {
// Update stuff
}
In case of the array arr, how can I declare an array, if I don't know it's size at the moment of the declaration in the header file?
How can class objects with constructors be declared in the header file, without passing in unknown parameters at that moment?
Thanks.
In case of the array arr, how can I declare an array, if I don't know
it's size at the moment of the declaration in the header file?
You can't! C++ does not support variable length arrays, although some compilers (such as GCC) add support for them as an extension.
Instead, you should consider using the std::vector container type, from the Standard Template Library.
In your header/declaration:
class SomeClass {
int num; // works fine
// float arr[]; // produces an error because size is not declared
std::vector<float> arr;
//...
};
And, for your setup() function:
void SomeClass::setup() {
num = 10; // easy peasy, works!
// arr = float some_arr[5 * num]; // error
arr.resize(5 * num); // Sets the size of the container
// Fill in the array...
for (int i = 0; i < 5 * num; i += num) {
arr[i] = 12; // You can access (valid) elements just like a normal array!
}
//...
}
In case you don't know the array size before hand you can use dynamic allocation feature in C++.
First declare your array variable as follow
float *arr;
Then you can allocate required size as follows
arr=new float[10];
To deallocate memory
delete[] arr;
If want to dynamically allocate objects then,Declare class as
ClassName *obj;
Then to allocate use
obj=new ClassName(your_parameters);
Then you can delete it using
delete obj;
TIP:
It is always a good practice make pointer variable NULL after you have de-allocated memory.
Do arr=NULL; and obj=NULL; after de-allocating
I was trying a random code to accept values using dynamic size. Surprisingly the for loop in the Accept function does not execute. Instead, the control directly leaves the function. Please explain what is the mistake here?
using namespace std;
#include<iostream>
class consequtive
{
public : int *ptr;
int size;
public :
consequtive(int size);
void Accept();
};
consequtive::consequtive(int size)
{
ptr = new int[size];
}
void consequtive :: Accept()
{
cout<<"Enter elements :: "<<endl;
for(int i = 0 ; i < size ; i++)
{
cin>>ptr[i];
}
}
int main()
{
int size = 0;
cout<<"Enter size ::";
cin>>size;
consequtive obj(size);
obj.Accept();
}
A few problems here.
You have a class parameter that has the same name as a member, which isn't really a problem, but is a source of confusion (As in your case).
You never set the member size to anything inside the constructor.
For number one, I would recommend renaming the class member size to size_ or something similar, since this creates a separation and makes the variables easier to distinguish from each other. As for as the second problem, I would change your constructor to the following:
consequtive::consequtive(int size) : size_(size) // Assuming the member is called `size_`
{
ptr = new int[size];
}
The code should work now, and uses a concept called member initializer lists. Not setting the variable size results in undefined behavior.
You forgot to initialize the size member variable.
You could do something like this:
consequtive::consequtive(int size)
: size(size),
ptr(new int[size])
{
}
You should also add a destructor to your class, to avoid a memory leak:
consequtive::~consequtive()
{
delete[] ptr;
}
This size in the class definition
public : int *ptr;
int size;
this size in the constructor implementation
consequtive::consequtive(int size)
and this size in the main function
int size = 0;
are all different variables. The latter two will both have the same value because of the way they are used, but one size can be changed to a different value without the other being aware. The bug in the asker's code is because the first size is never given a value and is used uninitialized.
Solution:
consequtive::consequtive(int size): ptr(new int [size]), size(size)
{
}
Here we are using the Member Initializer List. We don't gain much from its use in this case, but it is a very useful tool. More on that here: Why should I prefer to use member initialization list?
Be cautious when using a parameter or local variable with the same name as a member. The inner most identifier always wins so inside
consequtive::consequtive(int size): ptr(new int [size]), size(size)
{
// in here
}
the size variable is the parameter and not the member. You can this->size to explicitly state you want the member, but it is a better idea to not reuse the identifier at all. You could forget to prepend this-> and the compiler is unlikely to warn you of the mistake.
I am currently working on an dynamic memory container.
Basic idea of the class is that you should be able to get the iterator of an object if you really do not know it, without the use of a for loop throughout all the elements to boost performance. The issue I have is the following; when you pass your pointer address to the object you want to get the iterator of it type casts the object into the extended memory containers structures type. This type contains an extra element, an integer. (IteratorNum)
When following the code the integer within the function is set to correct value, as below would be 50. But when the returned value is set into the local integer used in the main function it is 200? I've been adding watches and cannot figure out how it is possible that the function returns 50 but value gets set to 200.
template <typename DataType> class MemoryContainer {
public:
struct LevelData : DataType
{
int element;
};
DataType &New()
{
elements++;
//Reallocate the size of the array
ld = (LevelData*)realloc(ld, sizeof(LevelData) * elements);
//Set the iteratorNumber
ld[elements - 1].element = elements - 1;
return ld[elements - 1];
}
DataType *reserve(int num)
{
return calloc(num, sizeof(DataType));
}
DataType &operator[](int i)
{
return ld[i];
}
bool inArray(DataType *type)
{
//Compare memory addresses and see if it's within.
return (type >= &ld[0]) && (type < &ld[elements - 1]);
}
static unsigned int getIterator(DataType *type)
{
// v this is 50, but in main says returns 200.
return ((LevelData*)type)->element;
}
MemoryContainer()
{
elements = 0;
}
~MemoryContainer()
{
free(data);
}
private:
unsigned int elements;
LevelData *ld;
};
struct Effective
{
//Set it to polymorphic classes
virtual void dummy()
{
}
char * testvar;
Effective(char * c)
{
testvar = c;
}
Effective(){}
};
MemoryContainer<Effective> myContainer;
int _tmain(int argc, _TCHAR* argv[])
{
//Create 200 elements in the array
for(int i = 0; i < 200; i++)
myContainer.New().testvar = "E";
//Add pointer for testing purposes to get the iterator.
Effective * pointer = &myContainer[50];
//Test setting it's value
pointer->testvar = "HEHEHE";
//Get iterator of our pointer in the array
unsigned int i = myContainer.getIterator(pointer);
printf(pointer->testvar);
system("PAUSE");
return 0;
}
I suspect it is the visual studio debugger getting confused between your two i variables. If you print out the value of i, it will print correctly. If you change the name of your variable to something else, the value shows as 50 in the debugger.
That said, your code is a mish-mash of c and c++ and won't work correctly with anything that requires a copy constructor. I would suggest at the very least using new [] rather than realloc.
Also, any user of this collection who tries to store a class with a member variable called element is going to get mighty confused.
The unsigned int i in the main function really has a value of 50, but the debugger is confusing it with the i declared in the for loop (I reproduced this with Visual Studio 2013). If you cout i it will be 50, and if you change the variable name it will show up as 50 in the debugger. I've never seen this problem before so I wonder if it might be due to your use of malloc/realloc/free with C++ objects.
I am having trouble with what seems like a very simple concept. I have a class like such:
class Projectile
{
public:
int count;
int projectiles[1][3];
Projectile();
void newProjectile();
};
Projectile::Projectile()
{
count = 0;
}
void Projectile::newProjectile()
{
projectiles[0][0] = { 1, 2, 3 };
}
I am trying to set the values inside the projectiles array, and I must be doing this incorrectly. How can I go about dynamically adding a set of values into this property?
projectiles[0][0] refers to a specific location in a two-dimensional array, its type is int
If you want to dynamically add items, then you can use std::vector<int> (see here)
projectiles[0][0] = { 1, 2, 3 };
This isn't correct. Initializer lists can only given at the point of declaration. You have to assign values independently to each location of the array elements. std::vector<std::vector> twoDimArray; is what you want.
struct foo{
std::vector<std::vector<int> > twoDimArray;
void create(int size){
std::vector<int> oneDimArray(size);
// vector as of now can just accommodate size number of elements. They aren't
// assigned any values yet.
twoDimArray.push_back(oneDimArray); // Copy it to the twoDimArray
// Now if you wish to increase the size of each row, just push_back element to
// that row.
twoDimArray[0].push_back(8);
}
};
try this
void Projectile::newProjectile()
{
projectiles[0][0] = 1;
projectiles[0][1]=2;
projectiles[0][2]=3;
}
I'm designing a game in C++ similar to Minecraft that holds an enormous amount of terrain data in memory. In general, I want to store an array in memory that is [5][4][5][50][50][50]. This isn't bad since it amounts to about 100mb of virtual memory since my structure will only be about 8 bytes.
However, I'm having trouble figuring out the best way to handle this. I do want this to be in virtual memory, but obviously not on the stack. And I keep making the mistake some how of creating this array on the stack an causing a stack overflow. What I would like to do is below. This is just code that I threw together to give you an example of what I'm doing, I have code with correct syntax on my machine, I just didn't want to clutter the post.
typedef struct modelBlock
{
// Information about the blocks
} BLOCK;
typedef struct modelGrid
{
bool empty;
BLOCK blocksArray[50][50][50];
} GRID;
class Parent
{
Child* child;
Parent(void);
}
Parent::Parent()
{
Child c;
child = &c;
}
class Child
{
GRID grids[5][4][5];
}
However, every time I do this, I cause a stack overflow (appropriate web site choice right?). I played with using pointer based arrays, but I had a lot of trouble with data being lost outside of its scope.
If anyone could give me some insight on how to get my data to store on the heap instead of the stack, or if I should use some other way of creating my array, I'd really appreciate the help. I'd like to avoid using vectors because of overhead, though I'm not sure how substantial it is.
Use boost::multi_array
If you want to allocate something on the heap, use new.
#include <memory>
class Parent
{
std::auto_ptr<Child> child; // use auto_ptr for dynamically-allocated members
Parent(const Parent&); // You probably don't want to copy this giant thing
public:
Parent();
};
Parent::Parent()
: child(new Child) // initialize members with an initializer list
{
}
Also, avoid mixing C and C++ styles. There's no reason to do
typedef struct blah{ ... } BLAH;
in C++. A struct is just a class with all of the members public by default; just like a class, you can refer to the struct type's name without using the struct tag. There's also no need to specify void for a function that takes no parameters.
boost::multi_array (linked in PigBen's answer) is a good choice over raw arrays.
If you want the class created on the heap, create it with new:
Child * c = new Child;
and then of course delete it, or better still use a smart pointer.
In order to do exactly what you're trying to do you have to declare everything as pointers (and pointers to pointers to pointers to pointers) and then allocate each one individually.
Teh sux!
A better option is to simply allocate the ginormous block in one chunk and use multiple variable along with pointer arithmetic to arrive at the correct location.
Edit: Wasn't paying attention and didn't notice your constructor. That's not only not the way to get your Child allocated on the free-store, it's a great way to create situations eliciting undefined behavior. Your Child will be gone when the constructor is through and the pointer to it will then be invalid. I wonder if you shouldn't run through some basic tutorials before trying to write a game.
Here's something that works and can be built upon without the boost dependency. One downside is it removes use of [][][] style of referencing elements, but it's a small cost and can be added.
template<class T>
class Matrix {
unsigned char* _data;
const size_t _depth;
const size_t _cols;
const size_t _rows;
public:
Matrix(const size_t& depth, const size_t& rows, const size_t& cols):
_depth(depth),
_rows(rows),
_cols(cols) {
_data = new unsigned char [depth * rows * cols * sizeof(T)];
}
~Matrix() {
delete[] _data;
}
T& at(const size_t& depthIndex, const size_t& rowIndex, const size_t& colIndex) const {
return *reinterpret_cast<T*>(_data + ((((depthIndex * _cols + colIndex) * _rows) + rowIndex) * sizeof(T)));
}
const size_t& getDepth() const {
return _depth;
}
const size_t& getRows() const {
return _rows;
}
const size_t& getCols() const {
return _cols;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Matrix<int> block(50, 50, 50);
size_t d, r, c;
for (d = 0; d < block.getDepth(); d++) {
for (r = 0; r < block.getRows(); r++) {
for (c = 0; c < block.getCols(); c++) {
block.at(d, r, c) = d * 10000000 + r * 10000 + c;
}
}
}
for (d = 0; d < block.getDepth(); d++) {
for (r = 0; r < block.getRows(); r++) {
for (c = 0; c < block.getCols(); c++) {
assert(block.at(d, r, c) == d * 10000000 + r * 10000 + c);
}
}
}
return 0;
}
A smaller example (with changed names for all the structs, to make the general principle clearer). The 'Bloe' struct is the one you want to allocate on the heap, and this is accomplished using 'new'.
struct Bla {
int arr[4][4];
};
struct Bloe {
Bla bla[2][2];
};
int main()
{
Bloe* bloe = new Bloe();
bloe->bla[1][1].arr[1][1] = 1;
return 0;
}
I did this by putting all the data in a binary file. I calculated the offset of the data and used seek() and read() to get the data when needed. The open() call is very slow so you should leave the file open during the lifetime of the program.
Below is how I understood what you showed you were trying to do in your example. I tried to keep it straightforward. Each Array of [50][50][50] is allocated in one memory chunk on the heap, and only allocated when used. There is also an exemple of access code. No fancy boost or anything special, just basic C++.
#include <iostream>
class Block
{
public:
// Information about the blocks
int data;
};
class Grid
{
public:
bool empty;
Block (*blocks)[50][50];
Grid() : empty(true) {
}
void makeRoom(){
this->blocks = new Block[50][50][50];
this->empty = false;
}
~Grid(){
if (!this->empty){
delete [] this->blocks;
}
}
};
class Parent
{
public:
Grid (* child)[4][5];
Parent()
{
this->child = new Grid[5][4][5];
}
~Parent()
{
delete [] this->child;
}
};
main(){
Parent p;
p.child[0][0][0].makeRoom();
if (!p.child[0][0][0].empty){
Block (* grid)[50][50] = p.child[0][0][0].blocks;
grid[49][49][49].data = 17;
}
std::cout << "item = "
<< p.child[0][0][0].blocks[49][49][49].data
<< std::endl;
}
This could still be more simple and straightfoward and just use one bug array of [50][50][50][5][4][5] blocks in one memory chunk on the heap, but I'll let you figure out how if this is what you want.
Also, usind dynamic allocation in class Parent only has the sole purpose to use heap instaed of stack, but for such a small array (5*4*5 pointers), allocating it on stack should not be a problem, hence it could be written.
class Parent
{
public:
Grid child[5][4][5];
};
without changing anything in the way it is used.