Declaring vectors inside for loop - c++

I have an array of pointers to vectors vector<int> *F[12]; and I wish to initialize some vectors and store their addresses in F.
for(uint i = A; i <= B; ++i){
vector<uint> newvec(pow2(i), 0);
F[i] = &newvec;
}
But when I try to access them later, I find that they are not all zero:
for(uint i = A; i <= B; ++i){
for(uint j = 0; j <= pow2(i); ++j){
if((*F[i]).at(j) != 0){
cout << i << "/" << j << "/" << (*F[i]).at(j) << "|";
}
}
}
I assume this has something to do with the scope of the declared vector. Why has the memory been freed? Do I have to use malloc and create a vector from that?

newvec is being created on the call stack each iteration. Each time through the loop you create it, make a pointer to it, then it vanishes. You want to use the 'new' operator to create a longer-lasting instance of the vector in the heap.

newvec goes out of scope when the loop exits. Any existing reference or pointer to it is invalid at that point. You'll need to declare the object at the appropriate scope (I don't know what that is for you in this case, but certainly outside the for loop).

Related

Scope of struct object in c++ created without new keyword

Coming from a Java background, following code is confusing me. Confusion here is C++ object creation without new keyword. I am creating this object Student_info info; and then adding it to a vector. Since I am not creating it using new keyword, will it be allocated on stack and be destroyed after the loop exits? If that is the case, how the last loop is able to extract the info from vector correctly? Shouldn't it throw exception as all the object added to the vector has been destroyed?
struct Student_info {
string name;
vector<double> marks;
};
int main()
{
int num = 2;
vector<Student_info> student_infos;
for (int i = 0; i < 3; i++) {
Student_info info; //will this object be destroyed once this loop exits?
cout << "Enter name:";
cin >> info.name;
double x;
cout << "Enter 2 marks";
for (int j = 0; j < num; j++) {
cin >> x;
info.marks.push_back(x);
}
student_infos.push_back(info);
}
for (int i = 0; i < 3; i++) {
cout << student_infos[i].name;
for (int j = 0; j < num; j++) {
cout << student_infos[i].marks[j];
}
cout << endl;
}
return 0;
}
You are correct in that the info object will be destroyed, but it is copied into the vector when using push_back. The rest of the code reads the copy from the vector and not the original object.
http://www.cplusplus.com/reference/vector/vector/push_back/
The copying is done using the object's copy constructor which in this case is compiler-provided. It will in turn call the copy constructors on the string and vector members of the struct.
The scope of variable info is the block scope of the for statement starting from the point of declaration of the variable.
for (int i = 0; i < 3; i++) {
Student_info info; //will this object be destroyed once this loop exits?
//...
}
Each time a new iteration of the loop is executed a new object with name info is created.
The scope of variable student_infos is the outer most block scope of function main where the variable is declared.
int main()
{
vector<Student_info> student_infos;
//...
}
When the loop is executed a new object is added to the vector that is a copy of variable info. The vector does not contain a reference to the original object with name info. It creates a copy of the object and stores it within itself internally.
Take into account that in general these loops
for (int i = 0; i < 3; i++) {
cout << student_infos[i].name;
for (int j = 0; j < num; j++) {
cout << student_infos[i].marks[j];
}
cout << endl;
}
are unsafe. It is much better to rely on the actual number of elements in the vectors. You could write instead
for ( vector<Student_info>::size_type i = 0; i < student_infos.size(); i++)
{
cout << student_infos[i].name;
for ( vector<double>::size_type j = 0; j < student_infos[i].marks.size(); j++)
{
cout << student_infos[i].marks[j];
}
cout << endl;
}
Yes, info will be destroyed at the end of the loop. push_back creates a new copy from info, so even if info is destroyed, its copy still exist in the vector.
It will copy the temp Student_info info to the student_infos when push_back is done. If you can write a custom copy constructor for Student_info and print something there you will see the copy construct will invoked.
Consider using,
http://en.cppreference.com/w/cpp/container/vector/emplace_back

c++ use & to create pointer member from objects in array [error]

Hello I am sorry this shouldn't be a hard problem. Im trying to get the pointer to call that objects function in the array. the block id is the key, however i cannot seem to get it running.
blocks* objects[28];
int index = 0;
for (int i = 0; i < 6; i++)
{
for (int j = i + 0; j < 6; j++)
{
objects[index] = new blocks(key, i, j);
key = key + 1; //used to make sure each block can id with a key
index = index + 1;
}
}
for (int i = 0; i < 28; i++)
{
double id = objects[i]->getblockid(); //FIXED
cout << "Object is: " << i << " id is: " << id << endl;
}
Are you saying that your code doesn't compile? It seems fine for me.
Howerver I can see see a few problems at runtime.
First, in inner loop you are instantiating block object 21 times, but you operate on only first 6 elements of this array. So when you are iterating from 0 to 28 in last loop, you will get exception thrown since 7th and further elements are not instantiated. This is because 7th element of this array is not instantiated. It points to some memory location which is just a garbage.
The other problem is that when you overwrite your pointers, you loose information of created objects, this causes memory leaks. Perhaps you should familiarize yourself with smart pointers concept?
Use std::vectors instead of vanila arrays. Alternatively use std::array.
You should also familiarize with concept of iterators.

Adding pointers to vector in loop

I am slightly confused about the following code
void foo() {
std::list<A*> list;
for (int i = 0; i < 3; i ++) {
A a = A(i);
list.push_back(&a);
}
for (Iterator it = list.begin(); it != list.end(); it++) {
std::cout << (*it);
}
}
which prints out three times the object a with constructor argument 2, i.e. the last object constructed in the loop.
What am I doing wrong here?
You have a list of dangling pointers.
for (int i = 0; i < 3; i ++) {
A a = A(i);
list(&a);
}
In each iteration, this loop creates an object of type A, which is immediately destroyed when the iteration completes. So the contents of the list are undefined. You would need something like this:
for (int i = 0; i < 3; i ++) {
A* a = new A(i);
list(a);
}
...but don't forget to delete them all in another loop when you're done with the list.
The variable a is local to the first for loop, so it is destroyed at the end of each iteration of the loop. This means that after the loop finishes, all three pointers in list point to objects that no longer exist. Dereferencing those pointers causes undefined behaviour.
If you'd like to worry less about remembering to de-allocate the allocated memory (and have a nicer less error prone code) you should use unique_ptr or shared_ptr (read about them and shoose whichever fits your needs best).
Here is a small example (notice how the elements in the vector get deleted when the vector goes out of scope):
cout<<"Scope begins"<<endl;
{
vector< unique_ptr<A> > v;
for (int i=0; i<5; ++i){
v.push_back(unique_ptr<A>(new A(i)) );
}
}
cout<<"Scope ends"<<endl;
Live demo here.

Program declaring variables by itself

I am still a ... novice, in c++.
I don't know the name of what I am looking for but
I 've been searching a lot but can't seem to find the answer to following question:
I want to write a program that would declare demanded number of variables.
Example:
int a;
cin>>a;
Now if "a" is 5 (or any other number), I want program to declare 5 more variables,
Names do not matter but let's say...n1,n2,n3,n4,n5.
I've tried array and for loop but can't get it to work.
I got answer on Croatian forum (forum.hr) but the forum is currently offline, so I had no
time to try it out...
It was about using heap instead of stack
Thx in advance
C++ has container classes for this purpose. In particular, you want a vector:
std::vector<int> a(size);
for (int i = 0; i < a.size(); ++i)
std::cin >> a[i];
Declares a vector a of integers of some size and reads its elements, one by one.
If this is C++, the best you can do is using std::vector as it will manage the memory for you.
you can store them in an array:
int a;
cin >> a;
int *number = new int[a]; // allocate an array of size a
for (int i = 0; i < a; i++) {
number[i] = 5 + i; // set your numbers to anything here
}
delete[] number; // otherwise you have memory leak
or better use a vector:
vector<int> number(a);
// iterate with a normal for loop
for (int i = 0; i < number.size(); i++) {
number[i] = 5 + i;
}
..
// or use iterators
for (vector<int>::iterator it = number.begin(); it != number.end(); ++it) {
cout << *it << endl;
}
so you don't have to manage memory.

Expanding a dynamically allocated array

I have allocated an array as follows.
#include <iostream>
int main() {
const int first_dim = 3;
const int second_dim = 2;
// Allocate array and populate with dummy data
int** myArray = new int*[first_dim];
for (int i = 0; i < first_dim; i++) {
myArray[i] = new int[second_dim];
for (int j = 0; j < second_dim; j++) {
myArray[i][j] = i*second_dim + j;
std::cout << "[i = " << i << ", j = " << j << "] Value: " << myArray[i][j] << "\n";
}
}
// De-allocate array
for (int i = 0; i < first_dim; i++)
delete[] myArray[i];
delete[] myArray;
}
Let's say I want to add a 4th element to the first dimension, i.e. myArray[3]. Is this possible?
I've heard that Vectors are so much more efficient for this purpose, but I hardly know what they are and I've never used them before.
Yes, but in a very painful way. What you have to do is allocate new memory which now has your new desired dimensions, in this case 4 and 2, then copy all the contents of your matrix to your new matrix, and then free the memory of the previous matrix... that's painful. Now let's see how the same is done with vectors:
#include <vector>
using std::vector;
int main()
{
vector< vector <int> > matrix;
matrix.resize(3);
for(int i = 0; i < 3; ++i)
matrix[i].resize(2);
matrix[0][1] = 4;
//...
//now you want to make the first dimension 4? Piece of cake
matrix.resize(4);
matrix[3].resize(2);
}
HTH
edit:
some comments on your original code:
In C++ ALL_CAP_NAMES usually refer to macros (something you #define). Avoid using them in other contexts
why do you declare FIRSTDIM and SECONDDIM static? That is absolutely unnecessary. If a local variable is static it means informally that it will be the same variable next time you call the function with kept value. Since you technically can't call main a second sime this is useless. Even if you could do that it would still be useless.
you should wrire delete [] array[i]; and delete [] array; so the compiler knows that the int* and int** you're trying to delete actually point to an array, not just an int or int* respectively.
Let's say I want to add a 4th element to the first dimension, i.e. myArray[3]. Is this possible?
Yes, but it's a pain in the neck. It basically boils down to allocating a new array, just as your existing code does (hint: put it in the function and make the sizes arguments to that function) and copying compatible elements over.
Edit: One of the things that std::vector does for you is properly de-allocating you memory. In the code you have, failure to allocate one of the arrays along the 2nd dimension will result in a memory leak. A more robust solution would initialize pointers to 0 before performing any allocation. An exception block could then catch the exception and free whatever was partially allocated.
Because this code becomes complex quickly, people resort to allocating a single buffer and addressing using a stride or using a 1D array of 1D arrrays (i.e. std::vector of std::vectors).