What is the reason for this pointer conflicts? - c++

Maybe I'm just confusing things a little bit.. But please consider this piece of C++ code:
#include <iostream>
#include <list>
using namespace std;
void printArray(int *arr, int n)
{
for(int i=0; i<n; ++i)
cout << arr[i] << " ";
cout << endl;
}
int main()
{
list<int*> arrays;
int times=20, v[9]={1,2,3,4,5,6,7,8,0};
arrays.push_back(v);
while(times--)
{
int *cur = arrays.front();
arrays.pop_front();
printArray(cur, 9);
int ta[9], tb[9];
for(int i=0; i<9; ++i)
{
ta[i] = *(cur+i)+1;
tb[i] = *(cur+i)-1;
}
arrays.push_back(&ta[0]);
arrays.push_back(&tb[0]);
}
return 0;
}
As you can see, the objective is to, beggining with a default array {1,2,3,4,5,6,7,8,0}, store (in times iterations) 2 variants of this array in a list of int pointers.
So, in the first iteration the 2 arrays {2,3,4,5,6,7,8,9,1} and {0,2,3,
,5,6,7,-1} should be stored in the list and thus, the first 3 printArray should be:
1 2 3 4 5 6 7 8 0
2 3 4 5 6 7 8 9 1
0 1 2 3 4 5 6 7 -1
Now, whats happening is that the first 3 printArray are:
1 2 3 4 5 6 7 8 0
2 3 4 5 6 7 8 9 1
2 3 4 5 6 7 8 9 1
I've already printed ta and tb at each iteration and I know that what's really being printed out is 1) default array, 2) first ta, 3) tb of the first ta. But I don't really know what's the reason for this behavior, I mean, aren't ta and tb new arrays (independent from the previous ones) in each iteration? If this is the case, my for is just assigning values for the new arrays positions, so why are they conflicting with each other?

The problem is quite simple, actually.
As #quimnuss stated in the comments, ta and tb were deallocating at some point and thus, the pointers saved in the list would point to something completely different from those arrays that were deallocated, leading to and undefined behavior of the program.
This statement makes complete sense since ta and tb are local variables of the while loop and so their validity will run out at each iteration completion.
We can workaround this problem by dynamically allocate memory at each iteration, like:
int *ta = new int[9];
int *tb = new int[9];
This away no loss of information will happen at every iteration end since the scope of this arrays are no longer local to the while loop.
Final code:
#include <iostream>
#include <list>
using namespace std;
void printArray(int *arr, int n)
{
for(int i=0; i<n; ++i)
cout << arr[i] << " ";
cout << endl;
}
int main()
{
list<int*> arrays;
int times=20;
int *v = new int[9];
for(int i=0; i<8; ++i)
v[i] = i+1;
v[8] = 0;
arrays.push_back(v);
while(times--)
{
int *cur = arrays.front();
arrays.pop_front();
printArray(cur, 9);
int *ta = new int[9];
int *tb = new int[9];
for(int i=0; i<9; ++i)
{
ta[i] = *(cur+i)+1;
tb[i] = *(cur+i)-1;
}
arrays.push_back(ta);
arrays.push_back(tb);
delete[] cur;
}
while(!arrays.empty())
{
int *p = arrays.front();
arrays.pop_front();
delete[] p;
}
return 0;
}

Related

Problem using iterators with dynamically allocated array

I have a variable k of type int to set the length of a dynamically allocated int array:
int *Numbers = new int[k];
But because of this I cannot iterate over the array, I get an error:
"no matching begin function was found required for this range-based for statement"
I also cannot get the length of the array using size();
Here's the complete code:
#include <iostream>
using namespace std;
int main()
{
int b, k;
cin >> b >> k;
int *Numbers = new int[k];
for (int i : Numbers) {// (There is a error)
}
for (int i = 0; i < size(Numbers); i++) {
}
}
Prefer using a std::vector instead of a std::array. (Like #tadman mentioned.)
Here is your code using std::vector instead:
#include <iostream>
#include <vector>
int main()
{
int b, k;
std::cin >> b >> k;
std::vector<int> Numbers(b,k); // Fills the vector "Numbers" with nth number of elements with each element as a copy of val.
for (int i : Numbers)
std::cout << i << std::endl;
for (int i = 0; i < Numbers.size(); i++)
std::cout << Numbers[i] << std::endl;
return 0;
}
Say I want 10 elements with the number 5.
Output:
10
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
Also consider not using namespace std;.
The simple and recommended solution is to use std::vector, however if you really want a dynamically allocated array and to use iterator like features on it, you can use iterator_range from boost library, which allows you to create an iterator range for it thus making it usable in range based for loops and in functions like std::size.
Live demo
#include <iostream>
#include<boost/range.hpp>
int main()
{
int k = 5;
int *Numbers = new int[k]{1,4,5,7,8};
auto arr = boost::make_iterator_range(Numbers, Numbers + k);
for (int i : arr) { //range based loop
std::cout << i << " ";
}
std::cout << std::endl << "Size: " << arr.size(); //print size
//or std::size(arr);
}
Output:
1 4 5 7 8
Size: 5
Range-based for loops work with arrays, but not work with pointers. The Actual issue is that arrays is actually a pointer and not an array.try to use simple array.
Using pointers is problematic for many reasons. The simple solution to your problem is to use a vector
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int b, k;
cin >> b >> k;
vector<int> Numbers(k);
for (int i : Numbers) {
cout << i << endl;
}
for (int i = 0; i < Numbers.size(); i++) {
cout << Numbers[i] << endl;
}
}
C array does not have default iterator and thus there is no begin() and end() functions that are used to iterate over array when you use statment like this:
for (int i : Numbers)
You can check range-for reference:
range_expression - any expression that represents a suitable sequence (either an array or an object for which begin and end member functions or free functions are defined, see below) or a braced-init-list.
Okay, so since the dynamic array does not have a default iterator, do not use the for-each loop, instead consider using the regular for loop.
Also, mind the the size function will not work for an array (or dynamic array) and you need to remember the size, since it's not possible to get the size from the pointer only. Hence, this code would work:
#include <iostream>
using namespace std;
int main()
{
int b, k;
cin >> b >> k;
int *Numbers = new int[k];
const int SIZE = k;
for (int i = 0; i < SIZE; i++) {
cout << i << ' ';
}
}
You need to dereference *Numbers by using the * if you want to iterate over the array because *Numbers is a pointer to an integer which points to the first element of your array.For Example :
#include <iostream>
using namespace std;
int main()
{
int k = 10;
int *numbers = new int[k];
//filling the array
for(int i = 0 ; i < k ; ++i) {
*(numbers + i) = i ;
}
//output array element
for(int i = 0 ; i < k ; ++i) {
cout << numbers + i << " is the address of "<<*(numbers + i) << endl;
}
return 0;
}
The output is :
0x6f1750 is the address of 0
0x6f1754 is the address of 1
0x6f1758 is the address of 2
0x6f175c is the address of 3
0x6f1760 is the address of 4
0x6f1764 is the address of 5
0x6f1768 is the address of 6
0x6f176c is the address of 7
0x6f1770 is the address of 8
0x6f1774 is the address of 9
Unfortunatly, you can't get the size of your array with *Numbers because it's not an array but a pointer.

Easy way to store structure pointer members within structure into a vector

I'm implementing a scheduling simulation. I'd really appreciate it if someone know me a easy way to store structure pointer variables within structure into a vector and to print out it for checking.
I Know how to put the Input_Data in the Array P_LU[i].Fixture_Type[j] as shown following. But i'd like to move the value stored in the Array P_LU[i].Fixture_Type[j] to the Vector.
This is a part of my simulation code.
/*Input_Data
3
3 1 4 4
3 1 5 1
3 1 5 1
*/
struct Struct_Order {
int Part_No;
int Due_Date;
int Part_Type;
int Pallet;
};
struct Struct_Pallet {
int Pallet_No;
int *Fixture_Type;
Struct_Order *Part;
};
// pallets with fixture types at LU station
P_LU = new Struct_Pallet[N_Pallet_LU];
for (int i = 0; i < N_Pallet_LU; i++)
{
int N_Fixture_LU;
fin >> N_Fixture_LU;
P_LU[i].Pallet_No = i;
P_LU[i].Fixture_Type = new int[N_Fixture_LU];
for (int j = 0; j < N_Fixture_LU; j++)
{
fin >> temp_fixture_type;
P_LU[i].Fixture_Type[j] = temp_fixture_type;
}
}
======> Question. I want to put int *Fixture_Type Struct_Order *Part in Struct_Pallet type vector , not array.
I do not know if my intentions were delivered. Just leave me a comment if you need more explanation.
Instead of using pointers and taking on the responsibility for tracking sizes, allocating memory, deallocating memory, etc, you can use std::vector, which will handle all that complexity for you:
#include <vector>
struct Order {
int part_no;
int due_date;
int part_type;
int pallet;
};
struct Pallet {
int pallet_no;
std::vector<int> fixture_types;
std::vector<Order> parts;
};
Here's some sample code built using the code you have in the OP
Live Demo
int main()
{
int num_pallets = 0;
std::cin >> num_pallets;
std::vector<Pallet> pallets;
pallets.reserve(num_pallets);
for (int i = 0; i < num_pallets; ++i)
{
Pallet next_pallet;
next_pallet.pallet_no = i;
int num_fixture_types = 0;
std::cin >> num_fixture_types;
next_pallet.fixture_types.reserve(num_fixture_types);
for (int j = 0; j < num_fixture_types; j++)
{
int temp_fixture_type = 0;
std::cin >> temp_fixture_type;
next_pallet.fixture_types.push_back(temp_fixture_type);
}
pallets.push_back(std::move(next_pallet));
}
for (const Pallet& next_pallet : pallets)
{
std::cout << "Pallet: " << next_pallet.pallet_no << std::endl;
std::cout << "Fixture types:\n\t";
for (int fixture_type : next_pallet.fixture_types)
std::cout << fixture_type << " ";
std::cout << std::endl;
}
}
Input:
3
3 1 4 4
3 1 5 1
3 1 5 1
Output:
Pallet: 0
Fixture types:
1 4 4
Pallet: 1
Fixture types:
1 5 1
Pallet: 2
Fixture types:
1 5 1

How to make arrays behave like vectors?

I want to have an array with initial size 4. The user can add as many elements(int type) to it. The function append() will be used for it. Also every time the size of the array is insufficient the same function will double its size and add the element to it.
#include <iostream>
using namespace std;
int n = 4;
int count = 0;
void append(int *a, int k)
{
if(count == n)
{
n *= 2;
int *b = new int[n];
for(int i = 0; i < count; ++i)
{
b[i] = a[i];
}
a = b;
}
a[count] = k;
++count;
}
void display(int *a)
{
for(int i = 0; i < count; ++i)
cout << a[i] << endl;
}
int main()
{
int *array = new int[n];
char t = 'y';
int num;
while(t != 'n')
{
cout << "Enter Value: ";
cin >> num;
append(array, num);
cout << "Do you want to enter more values?(y/n): ";
cin >> t;
}
cout << "The values entered are:\n";
display(array);
return 0;
}
After giving the following values for entering into the array:
1
2
3
4
5
6
7
8
8
9
10
11
12
13
15
I am getting the following output(using display() function)
1
2
3
4
0 [(This value depends on the compiler) #Erroneous Output]
6
7
8
1 [(This value depends on the compiler) #Erroneous Output]
10
11
12
13
14
15
I do not know why I am getting random values for the elements entered just after the array is updated(size is doubled), and how I should fix it.
Vectors, in essence are just dynamically allocated arrays. My question here is why not just use a vector with 4 slots initially. std::vector<int>(4); will do the trick although if you are adamant on remaking the vector class, research the topic of dynamic arrays and create a c++ template class based off them. According to my understanding .append() deallocates all elements in the vector, then reallocates them with the extra element at the end.
There are many articles online created by people trying to accomplish similar tasks, just do a little bit of digging around:
http://www.gamedev.net/topic/528822-c-writing-my-own-vector-class/
https://codereview.stackexchange.com/questions/50975/creating-a-custom-vector-class

Filling a vector of pointers to vectors is producing weird results

Introduction
I have a code where I fill a vector with integer values and and push it into a vector of pointer to vectors as follows:
std::vector<std::vector<int>*> set_of_vectors;
for(int i = 0; i < 10; i++)
{
//initialize vector
std::vector<int> pos_vector;
//fill it with 0s
pos_vector.resize(10, 0);
//fill it with integers
fill_vector(pos_vector);
//push into set_of_vectors
set_of_vectors.push_back(&pos_vector);
}
The problem is the output is really weird. The output should shou be equal to
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
but on the contrary I am getting the following output:
9617952, 0, 2, 3, 4, 5, 6, 7, 8, 9,
Full Source code
#include <vector>
#include <iostream>
void fill_vector(std::vector<int> & values);
int main()
{
std::vector<std::vector<int>*> set_of_vectors;
for(int i = 0; i < 5; i++)
{
std::vector<int> pos_vector;
pos_vector.resize(10, 0);
fill_vector(pos_vector);
set_of_vectors.push_back(&pos_vector);
}
for(auto & vec:set_of_vectors)
{
for(auto &v:*vec)
{
std::cout << v <<", ";
}
std::cout << std::endl;
}
return 0;
}
void fill_vector(std::vector<int> & values)
{
for(int i = 0; i < values.size(); i++)
{
values[i] = i;
}
}
This is UB.
pos_vector is a local variable and will be destroyed when get out of the for loop, then the pointer pushed into vector (i.e. &pos_vector) will be a dangled pointer, any deference on it is UB.
If you have to use std::vector<std::vector<int>*>, you need to new a pointer:
for(int i = 0; i < 5; i++)
{
std::vector<int>* pos_vector = new std::vector<int>;
pos_vector->resize(10, 0);
fill_vector(*pos_vector);
set_of_vectors.push_back(pos_vector);
}
Don't forget to delete them at last.
Your are adding pointers to local objects. These local objects will be destroyed at the end of each for-loop and you keep a vector with pointers pointing to garbage ("dangling pointers").
You could define a std::vector<std::vector<int>> set_of_vectors and use &set_of_vectors[idx] to get a pointer for each element.
The following code creates a list of pointers from a list of vectors and can be used in your library call:
std::vector<std::vector<int>*> set_of_ptrs;
set_of_ptrs.reserve(set_of_vectors.size());
for(auto& v: set_of_vectors)
set_of_ptrs.push_back(&v);
You have to do something like
for(int i = 0; i < 5; i++)
{
std::vector<int>* pos_vector = new std::vector<int>();
pos_vector->resize(10, 0);
fill_vector(*pos_vector);
set_of_vectors.push_back(pos_vector);
}
Your example leaves you with dangling pointers for pos_vector addresses allocated on the stack.
You have to copy the vector into the array, pos_vector is a local variable and storing its reference will lead to undefined behavior as the vector is deleted once it goes out of scope. You should also define set_of_vectors as a std::vector of type std::vector<int> and not of std::vector<int>* as you do not want to store pointers there that will go out of scope.
#include <vector>
#include <iostream>
void fill_vector(std::vector<int>& values)
{
for(int i=0; i<values.size(); ++i)
values[i] = i;
}
int main()
{
std::vector<std::vector<int>> set_of_vectors;
for(int i = 0; i<5; ++i)
{
std::vector<int> pos_vector;
pos_vector.resize(10, 0);
fill_vector(pos_vector);
set_of_vectors.push_back(pos_vector);
}
for(auto& vec : set_of_vectors)
{
for(auto& v : vec)
{
std::cout << v <<", ";
}
std::cout << std::endl;
}
return 0;
}
You can simplify your assignment considerably with the help of the std::iota function.
std::vector<std::vector<int>> set_of_vectors(5, std::vector<int>(10));
for(auto& vec : set_of_vectors)
std::iota(vec.begin(), vec.end(), 1);

Reverse Array in C++

I have successfully reversed a 1-D array but when I cout the contents, it prints out the contents then bunch of other numbers.
4
3
2
1
-858993460
-858993460
4
-858993460
-1021245226
12384668
3697177
1
14484784
14501672
-1021245434
0
Press any key to continue . . .
I can't tell why it's printing out those extra numbers. Below is my source code:
#include <iostream>
#include <array>
using namespace std;
void flipRow(int array[], int row) {
int temp;
for (int i = 0; i < sizeof(array)/2; i++) {
//cout << "Hi" << endl;
temp = array[i];
array[i] = array[row-1];
array[row-1] = temp;
row--;
}
}
int main() {
const int ROW = 4;
int array[ROW] = { 1, 2, 3, 4 };
flipRow(array, ROW);
for (int i = 0; i < sizeof(array); i++) {
cout << array[i] << endl;
}
system("pause");
return 0;
}
Are those addresses? Can someone tell why it's printing them out? Thank you.
Modify your for loop in main so the condition part of it becomes i < ROW and modify the for loop in flipRow so the condition part there reads i < row/2. sizeof operator returns the size of your array in bytes. You have four elements in your array and they are of type integer, which on your platform is 4 bytes, so your call to sizeof is returning 16.