I would like to write to internal array of vector. I could write using data() if vector is initialised.
However if the vector is empty (but having enough storage), I am not able to write directly to internal array of vector.
#include <vector>
#include <iostream>
using namespace std;
void write_seq(int *v, size_t len)
{
for (int i = 0; i < len; i++)
v[i] = i;
}
int main(void)
{
vector<int> v;
cout << "reserve and write\n";
v.reserve(10);
write_seq(v.data(), v.capacity());
cout << "seq length " << v.size() << "\n";
return 0;
}
Output:
$ g++ main.cpp && ./a.out
reserve and write
seq length 0
How to avoid this kind of situations, is it possible to validate data() pointer of vector?
Edit:
I assumed two things with this question, on an empty vector v;,
v.reserve(10) allocates memory for 10 elements and
v.data() points to that allocated memory.
You want to use resize, not reserve, and size instead of capacity. reserve simply gives the vector the added capacity, without actually increasing the size. resize increases the size to match the reserved capacity.
There's no need to concern yourself with how much memory you need to reserve beforehand. If performance is not really an issue, you may consider instead using auto-resizable back inserting iterators to push the elements at the step you want to push them.
#include <vector>
#include <iostream>
template<typename Iterator>
void write_seq(Iterator v) {
for (int i = 0; i < 10; i++) {
*v = i; // actually calls std::vector<>::push_back() internally
v++;
}
}
int main(void)
{
std::vector<int> v;
std::cout << "just write them data!\n";
write_seq(std::back_inserter(v));
std::cout << "seq length " << v.size() << "\n";
return 0;
}
You need to understand the concept of size and capacity of a vector. size is the number of elements stored while capacity is internal space allocated. capacity is always great than or equal to size. If you insert elements into the vector and caused the vector to run out of capacity, it will automatically increase its capacity by allocating a new space twice of current capacity, then copy existing elements into the new space, then delete the old space.
If you are planning to insert a large number of elements into a vector, the "auto increasing capacity" feature is not efficient, as it will keep allocating new spaces and copying elements. Instead, you can use reserve() to allocate enough space beforehand, and thus to avoid the process to keep allocating new spaces.
capacity(): Returns the number of elements that the container has currently allocated space for.
reserve(): Increase the capacity of the vector to the given size or more.
size(): Returns the number of elements in the container.
resize(): Changes the number of elements stored.
Back to your question, you can simply replace reserve with resize:
int main(void)
{
vector<int> v;
cout << "reserve and write\n";
v.resize(10); // use resize() instead of reserve()
write_seq(v.data(), v.size());
cout << "seq length " << v.size() << "\n";
return 0;
}
Or, you can insert into the vector directly:
void write_seq(vector<int>& v, size_t len)
{
for (int i = 0; i < len; i++)
v.push_back(i); // add an element to the vector, this changes the size
}
int main(void)
{
vector<int> v;
cout << "reserve and write\n";
v.reserve(10); // this does not change size, the vector is still empty
write_seq(v, v.capacity());
cout << "seq length " << v.size() << "\n";
return 0;
}
You cannot assign to an element that does not exist. Allocating memory is not sufficient, but your code is fine when you resize the vector (or create it with sufficient elements):
int main(void)
{
vector<int> v(10); // vector with 10 element
write_seq(v.data(), v.size()); // write to those 10 element
cout << "seq length " << v.size() << "\n"; // size is (still) 10
return 0;
}
Note that your code is not very idomatic. I assume you have reasons for that, but passing iterators to write_seq would be much more natural.
Related
So I am trying to use a dynamic array for my program and I do not know if I am doing it right. Should I use const int or just an int only?
int size = 1;
int *num1 = new int [size];
int *num2 = new int [size];
or
const int size = 1;
int *num1 = new int [size];
int *num2 = new int [size];
If the size is a compile-time constant that you want to create an "array" from, then I suggest std::array, as in
std::array<int, 1> num1;
If the size isn't known at compile-time then use std::vector, as in
std::vector<int> num1(size);
And if you really have to use explicit dynamic allocation then opt for smart pointers like std::unique_ptr, like
auto num1 = std::make_unique<int[]>(size);
As for if the variable size should be const, constexpr, not qualified at all, or if you should possible use the literal value directly when allocating, then it really depends on use-case, value availability, and personal preference.
On another note, for a size you should rather use the size_t type instead of int. Most programmers will immediately understand that when you use size_t the variable is used to store a size. Otherwise if you use int it could be any arbitrary integer value. Furthermore, size_t is an unsigned type, so it doesn't allow negative numbers, which is one less cause of problems.
I've seen you ask a few questions about this now, so I want to show you the difference between having to resize a dynamic array and using std::vector, which packages all of the features you'd want in a dynamically-sized block of contiguous memory.
The following code is how to increase a dynamic array to hold user input. We don't know how long the user wants to input numbers for, so we have to keep resizing every time they enter a new number.
int number = 0;
std::size_t array_size = 0; // we need to track the size of the thing
int *array = nullptr; // nothing in here yet
std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
// we need to request more memory
++array_size;
int *new_array = new int[array_size];
// we have to copy the old array to the new array
// fun note: as pointed out in the comments below, using memcpy on
// either src or dest == nullptr is undefined behavior. Just goes to
// show how hard it is to get something like this correct.
// Don't do this when we have perfectly good STL containers!
std::memcpy(new_array, array, (array_size - 1) * sizeof(int));
// delete the old array, if it exists (we can safely call delete on a nullptr)
delete[] array;
// assign the new block of memory to array
array = new_array;
// add the retrieved element to array
array[array_size - 1] = number;
std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// output the array
for (std::size_t i = 0; i < array_size; i++)
{
std::cout << array[i] << "\n";
}
// all done, delete the memory that was allocated
delete[] array;
array = nullptr; // not strictly required, but can prevent us from accidentally deleting the same block of memory twice, which would be bad
We can do the same thing using std::vector:
int number;
std::vector<int> vec; // this is a vector that holds ints, it tracks its own size and memmory
std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
vec.push_back(number); // all done
std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
for (std::size_t i = 0; i < vec.size(); i++)
{
std::cout << vec[i] << "\n";
}
// or we can used range-based for loops, which are awesome
for (auto& v : vec)
{
std::cout << v << "\n";
}
Note that in the std::vector example, I'm outputting the contents of the std::vector twice, just to show that we have an option for iterating through a vector that is not available for an int *. We don't need to keep track of memory. We don't need to new and delete. When the current program scope exits (if this is a function, for example), the destructor of the std::vector is called and cleans up memory for us.
USE VECTORS!!!
I am a student and my teacher gave me this "homework".
I have to build a dynamic stack, the trivial part is that I mustn't use a list structure (e.g. linked lists). What I thought was that an array implementation was the bets thing, but during the development I stopped at the point I had to increment the array size. I can't figure out how to increment the size without losing data. Can someone help me ?
One thing you can do is creating a new array with the new size and then copying the old one in it. Something like this is what you're looking for?
const int new_size = old_size + 1;
int new_array[new_size];
std::copy(old_array, old_array+old_size, new_array);
I assume that your not allowed to use std::vector and that you must use dynamic memory allocation.
In that case when you run out of space in the currently allocated array, you'll have to do something like:
create an array larger than the current array size
copy current array to the new array
make the new array the current
delete the old array
Here is a simple and incomplete class to illustrate the idea.
#include <iostream>
#include <algorithm>
using namespace std;
class myStack
{
size_t capacity {0};
size_t size {0};
int *data {nullptr};
public:
void push(int n)
{
if (size == capacity)
{
cout << "Increase capacity by 5 elements" << endl;
capacity += 5;
int* tmp = new int[capacity];
copy_n(data, size, tmp);
swap(data, tmp);
delete[] tmp;
}
data[size] = n;
++size;
}
void print_all()
{
cout << "capacity=" << capacity << endl;
for (size_t i = 0; i < size; ++i)
cout << data[i] << " ";
cout << endl;
}
};
int main(void) {
myStack s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
s.print_all();
s.push(6);
s.print_all();
return 0;
}
Output:
Increase capacity by 5 elements
capacity=5
1 2 3 4 5
Increase capacity by 5 elements
capacity=10
1 2 3 4 5 6
I'll leave the rest to you for practice (e.g. destructor to delete allocated memory, top to read data, pop to remove elements etc.) Probably you would also like to turn it into a template so that you can handle other data types than int with the same code.
Notice: This simple class just grows the capacity by 5 when necessary. A more common approach is to double the capacity when an increase is needed. I'll leave that to you as well so that you can practice.
I have this C++ structure:
typedef unsigned long T;
struct Node {
T index;
T length;
Node(): index(0), length(0), next(0) {}
Node(const T &ind, const T &len): index(ind), length(len), next(0) {}
vector<Node*> next;
};
I'm trying to find out how much memory next will take. I know that it will have five elements maximum. So here's what I do:
int main(int argc, const char * argv[]) {
Node n;
Node* x = new Node(3, 4);
cout << "An empty vector of pointers: " << sizeof(n.next) << " bytes\n";
// Add five elements
for(int i = 0; i < 5; i++)
n.next.push_back(x);
cout<< "New size of the vector of pointers: " << n.next.size() << " elements\n";
cout<< "New size of the vector of pointers: " << sizeof(n.next) << " bytes\n";
return 0;
}
And here's my output:
An empty vector of pointers: 24 bytes
New size of the vector of pointers: 5 elements
New size of the vector of pointers: 24 bytes
My question: how is that possible that an empty vector takes 24 bytes, but the same vector with 5 elements in it still takes 24 bytes? Shouldn't it take more memory? Like *24 + 5 * sizeof(Node*)*?
Vector is a dynamic structure that has a fixed "footprint", which usually contains pointers to dynamically-allocated data.
n.next.size() returns the size of dynamically allocated data. sizeof(n.next) returns the size of the fixed footprint.
All objects of a given type are the same size, and sizeof(n.next) is equivalent to sizeof(vector<Node*>).
A vector instance doesn't contain the elements, it only points to them, so the instance itself is always the same size.
It works exactly like this:
class A
{
public:
A(int n) : p(new char[n]), s(n) {}
int size() const { return s; }
private:
char* p;
int s;
};
int main()
{
A a(1);
A b(100);
// These all print the same thing:
std::cout << sizeof(a);
std::cout << sizeof(b);
std::cout << sizeof(A);
// These are different:
std::cout << a.size(); // Prints 1
std::cout << b.size(); // Prints 100
}
If you want to find out how much space your vector occupies in total, you need to calculate that yourself.
You want n.next.size().
sizeof is entirely a compile-time operation, since it just looks at the type to figure out how many bytes you need for storing one instance of it. sizeof(n.next) tells you how many bytes it takes to hold n.next. Since it's a vector, it's likely to be implemented using 3 pointers (8 bytes each) -- one pointing at the start of the allocated array, one pointing at the end of the data, one pointing at the end of the allocated array.
The vector implementation that comes as a standard is typically optimized to start its life with more than the necessary amount of space. In simple terms, the implementation plans space for a vector on - for example - 8 objects even though you ask for less, and only starts allocating more memory once you get over this number.
This wastes some small amount of memory, if you never use those elements, but removes the performance overhead of reallocating memory for each element you add. The exact amount is implementation dependent, and some might not do it that way, but it is a typical optimization.
If you want to measure the space an element uses up, you need to go for larger amounts; for example, put 100 objects in and check, and then put 200 in and check. For small amounts, you will see a constant size, until you hit the threshold.
I am trying to write code in C++ that reads from a file, a sequence of points, stores it in a dynamic array and then prints back.
This is the specification I've been given:
"We want to take advantage of the fact that we can use dynamic memory, thus instead of allocating at beginning an amount of memory large enough according to our estimations, we implement the following algorithm:
Initially, very little memory is allocated.
At each iteration of the loop (reading from the file and storing into the
dynamic array) we keep track of:
The array maximum size (the allocated memory).
The number of elements in the array.
When, because of a new insertion, the number of elements would become
greater than the array maximum size, memory reallocation needs to take
place as follows:
Allocate another dynamic array with a greater maximum size.
Copy all the elements from the previous array to the new one.
Deallocate the memory area allocated for the previous array.
Get the pointer to the previous array to point to the new one.
Add the new item at the end of the array. This is where my problem is.
From my code below, I think everything else is fine but the last requirement, which is to add the new item at the end of the array.
The code works fine when the array Max_Size exceeds file's number of
elements, but when I try extending the num_elements, the result is
that the extra digits in the file are just saved as zeros
.
Also to add, the assignment doesn't allow use of vectors just yet.
Sorry I forgot to mention this, I'm new to stackoverflow and somewhat
to programming.
Any help please
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct point {
double x;
double y;
};
int main () {
ifstream inputfile;
inputfile.open("datainput.txt");
if(!inputfile.is_open()){
cout << "could not open file" << endl;
exit(EXIT_FAILURE);
}
//initially very little memory is allocated
int Max_Size = 10;
int num_elements = 0;
point *pp = new point[Max_Size];
//read from file and store in dynamic array
for (int i = 0; !inputfile.eof(); i++) {
inputfile >> pp[i].x >> pp[i].y;
num_elements++; //keep track of number of elements in array
}
//detecting when number of elements exeeds max size due to new insertion:
if (num_elements > Max_Size){
// allocate another dynamic array with a greater maximum size
Max_Size *= 2; // Max_Size = 2*Max_Size to double max size whenever there's memory problem
point *pp2 = new point[Max_Size];
//copy all elements from previous array to new one
for (int j=0; j<(Max_Size/2); j++) {
pp2[j].x = pp[j].x ;
pp2[j].y = pp[j].y;
}
//deallocate memory area allocated for previous array
delete [] pp;
//get pointer to previous array to point to the new one
pp = pp2;
**//add new item at end of the array
for (int k = ((Max_Size/2)-1); k<num_elements; k++) {
inputfile.seekg(k, ios::beg) >> pp2[k].x;
inputfile.seekg(k, ios::beg) >> pp2[k].y;
}**
//print out dynamic array values
for (int l = 0; l<num_elements; l++) {
cout << pp2[l].x << ",";
cout << pp2[l].y << endl;
}
//delete dynamic array
delete [] pp2;
}
else {
//print out dynamic array values
for (int m = 0; m<num_elements; m++) {
cout << pp[m].x << ",";
cout << pp[m].y << endl;
}
//delete dynamic array
delete [] pp;
}
cout <<"Number of elements = " << num_elements <<endl;
//close file
inputfile.close();
return 0;
}
Others have already pointed out std::vector. Here's roughly how code using it could look:
#include <vector>
#include <iostream>
struct point {
double x;
double y;
friend std::istream &operator>>(std::istream &is, point &p) {
return is >> p.x >> p.y;
}
friend std::ostream &operator<<(std::ostream &os, point const &p) {
return os << p.x << "," << p.y;
}
};
int main() {
// open the file of data
std::ifstream in("datainput.txt");
// initialize the vector from the file of data:
std::vector<point> p {
std::istream_iterator<point>(in),
std::istream_iterator<point>() };
// print out the data:
std::copy(p.begin(), p.end(), std::ostream_iterator<point>(std::cout, "\n"));
}
On top of being a lot shorter and simpler than the code you posted, getting this to work is likely to be a lot simpler and (as icing on the cake) it will almost certainly run faster1 (especially if you have a lot of data).
1. In fairness, I feel obliged to point out that the big difference in speed will mostly come from using \n instead of endl to terminate each line. This avoids flushing the file buffer as each line is written, which can easily give an order of magnitude speed improvement. See also: https://stackoverflow.com/a/1926432/179910
The program logic is flawed. You run the loop until EOF but you don't check to see if you have exeeded your array size. I would add an if statement inside of the first loop to check if you have passed the Max_Size. I would also write a function to reallocate the memory so you can simply call that function inside of your first loop.
Also you have problems with your memory allocation. You should do like this:
point temp = pp;
pp = new Point[...];
// Copy the contents of temp into pp
delete temp;
You need to set your pointer to the old array first so you don't lose it. Then after you have copied the contents of you old array into the new array, you can then delete the old array.
void pre_process(string& pattern, vector<int>& c)
{
c.reserve(pattern.length());
c[0] = -1;
c[1] = 0;
for(int i=2; i<pattern.length(); ++i)
{
if(pattern[c[i-1]] == pattern[i-1])
c[i] = c[i-1]+1;
else
c[i] = 0;
}
cout << c.size() << endl; //why the size is zero here?
}
After reserving the space in vector, I am assigning values to different positions of vector. So shouldn't the size be increased?
What is the right way to use vector as a fixed length container?
Because std::vector::reserve doesn't resize a vector. It simply re-allocates a larger chunk of memory for the vector's data (and copies elements from the original if necessary).
You need std::vector::resize for that:
c.resize(pattern.length());
Currently, you are accessing c out of bounds.
Alternatively, you can keep the call to resize and use push_back instead of operator[]
c.reserve(pattern.length());
c.push_back(-1);
c.push_back(0);