C++ Creating Dynamic 2D Array With One Statement but Without auto - c++

I've seen that a dynamic 2D array in C++ can be created as follows:
auto arr{ new int[nRows][nCols] };
nRows and nCols are compile-time known and the size of the array will not change during runtime.
I've tested what is the type of arr is PAx_i (where x is nCols). But I cannot figure out what to put instead of auto (if I don't want to use it) to create a dynamic 2D array with a single statement.
So, the question: Is it possible in C++ to specify the type of a dynamic 2D array directly (C-style like)? If yes, how?

C++ does not support dynamically-sized raw arrays (aka Variable Length Arrays, or VLAs). Whenever you come across the need for such a dynamic array (how ever many dimensions it may have), you should be immediately thinking of using the std::vector container.
Once properly created, you can use the [] operator (concatenated, for 2-D vectors) in much the same way as you would with raw arrays.
Here's a short code demo that creates a dynamic, 2-dimensional 'array' of integers, using the std::vector class, and initializes all elements with an especially significant, non-zero value:
#include <iostream>
#include <vector>
int main()
{
size_t nCols, nRows;
std::cout << "Enter nRows and nCols: ";
std::cin >> nRows >> nCols;
if (nCols < 2 || nRows < 2) {
std::cout << "Matrix is too small!\n";
return 1;
}
// The following SINGLE LINE declares and initializes the matrix...
std::vector<std::vector<int>> arr(nRows, std::vector<int>(nCols, 42));
std::cout << "nRows = " << arr.size() << "\n";
std::cout << "nCols = " << arr[0].size() << "\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
// Demo for how to use the "[][]" operator ...
arr[0][0] = arr[nRows - 1][nCols - 1] = 33; // Change 1st and last
std::cout << "------------\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
return 0;
}
One of the great benefits of using std::vector over new[] is that you don't have to worry about subsequently calling delete[] – the container class takes care of all memory allocation and deallocation internally.

In C++ try to avoid new/delete unless you have no other choice.
Next up is std::make_unique (or std::make_shared).
For dynamic arrays C++ has 'std::vector'
Like this :
#include <vector>
#include <iostream>
int main()
{
// 2x2 vector
std::vector<std::vector<int>> values{ {0,1},{2,3},{4,5} };
std::cout << values[1][1];
return 0;
}

Thusly, vector of vector, in this case the values are uninitialized.
std::vector<std::vector<int>> arr(nRows,std::vector<int>(nCols));
You can also do this with gcc compiler, but its not per standard, and won't work if nRows or nCols is variable in Visual Studio:
int arr[nRows][nCols];
It's better for you to get comfortable with C++ standard library, as it will open up new worlds for you.
Another way:
int *arr = new int[nRow*nCol];
You can then index into the flat buffer like:
arr[0][1]

Related

What is the proper way to create a dynamic array of unique_ptr's in c++11?

I would like to identify a canonical approach to allocating the equivalent of an array of pointers to pointers to int (like: int ** int_array), but using unique_ptr.
I would like a C++11 solution that is extensible to an array of pointers to pointers to an instance of a class, if possible (I've used ints here to simplify, and I realize there may be other issues when using class instances).
I understand how to create a fixed-size array of unique_ptr where the size is known in advance. The goal is to do the same where the array size is not known.
I have looked at a number of related solutions including the one below, but they seem to deal only with fixed allocation of unique_ptr arrays (that is, the size of the array of unique_ptr is already known in advance):
Proper way to create unique_ptr that holds an allocated array
I've implemented a simple program that attempts to demonstrate and compare 3 approaches: traditional dynamic creations of pointers, a fixed array of unique_ptr, and the goal: a dynamic array of unique_ptr.
#include <iostream> // include iostream
#include <memory> // include memory
using namespace std;
int main() {
cout << "Testing dynamic arrays of pointers\n";
int **num_array; // typical dynamic array of pointers to int
int count; // count of ints the user wants to generate
unique_ptr<int[]> f_num_array(new int[200]());
// above: fixed array of unique pointers to int - not what I want
unique_ptr<int[]> u_num_array;
// above: GOAL: dynamic array of unique pointers to int
int sum, u_sum, f_sum;
// above: test sum of each type of array (should match user count)
cout << "How many pointers would you like? ";
cin >> count; // get user input
num_array = new int*[count]; // allocate array of pointers on heap
//u_num_array = new int[count](); // GOAL - would like to do this
// above: ERROR: no overload for =; cannot allocate this way
for(int i=0; i<count; i++) { // allocate ints and store pointer
num_array[i] = new int(1); // pointer to an int on the heap
f_num_array[i] = 1; // assign 1 to the pre-allocated unique pointer array
unique_ptr<int> u_tmp(new int(1)); // temporary unique_ptr to int
// u_num_array[i] = u_tmp; // GOAL - would like to do this...
// ERROR: cannot assign unique_ptr this way
}
sum = 0; f_sum = 0; u_sum = 0; // init our sums to verify
for(int i=0; i<count; i++){
sum += *(num_array[i]); // summing our traditional array of pointers
f_sum += f_num_array[i]; // summing our fixed unique array of pointers
}
cout << "Sum = " << sum << "\n";
cout << "Sum (fixed unique_ptr array) = " << f_sum << "\n";
cout << "Sum (dynamic unique_ptr array) = " << u_sum << "\n";
delete[] num_array; // delete the dynamic array
f_num_array.release(); // delete the dynamic array
cout << "\nDone!\n";
}
#include <iostream>
#include <memory>
#include <vector>
int main() {
std::cout << "Testing dynamic arrays of pointers\n";
//int **num_array; - Never use except you are forced by some external interface.
int count = 0; // Always initialize variables
std::vector<std::unique_ptr<int>> num_array;
std::cout << "How many pointers would you like? ";
std::cin >> count; // get user input
num_array.resize(count);
for (auto& p : num_array) // You can do it with some algorithm, but I prefer this way
p = std::make_unique<int>(1);
int sum = 0; // Don't declare variables before you use them.
for (auto& p : num_array)
sum += *p;
std::cout << "Sum = " << sum << "\n";
num_array.clear();
std::cout << "\nDone!\n";
}

Getting out-of-range error when trying to create and populate a vector using a for loop (C++)

I'm trying to create a vector where each element is a multiple of 3 below 1000. I tried two ways, only one of which worked. The non-functioning way was:
int main() {
vector<int> multiples_of_three;
for (int i = 0; i <= 1000/3; ++i)
multiples_of_three[i] = 3*i;
cout << multiples_of_three[i] << "\n";
}
That gave an out of range error specifically on multiples_of_three[i]. This next bit of code worked:
int main() {
vector<int> multiples_of_three(334);
for (int i = 0; i < multiples_of_three.size(); ++i) {
multiples_of_three[i] = 3*i;
cout << multiples_of_three[i];
}
So if I defined the size of the vector I could keep it within it's constraints. Why is it that if I try and let the for loop dictate the number of elements I get an out of range error?
Thanks!
This works perfectly fine:
#include <iostream>
#include <vector>
using namespace std;
//this one is the edited version
int main() {
vector<int> multiples_of_three(334); //notice the change: I declared the size
for (int i = 0; i <= 1000 / 3; ++i){
multiples_of_three[i] = 3 * i;
cout << multiples_of_three[i] << "\n";
}
system("pause");
}
Consider these two examples below:
//=========================the following example has errors =====================
int main() {
vector<int> multiples_of_three;
multiples_of_three[0] = 0; // error
multiples_of_three[1] = 3; // error
cout << "Here they are: " << multiples_of_three[0]; cout << endl;
cout << "Here they are: " << multiples_of_three[1]; cout << endl;
cout << endl;
system("pause");
return 0;
}
//============================the following example works==========================
int main() {
vector<int> multiples_of_three;
multiples_of_three.push_back(0);
multiples_of_three.push_back(3);
cout << "Here they are: " << multiples_of_three[0]; cout << endl;
cout << "Here they are: " << multiples_of_three[1]; cout << endl;
cout << endl;
system("pause");
return 0;
}
So unless, you have declared the size, never use indices directly for assigning values (as in the first example). However, if the values have already been assigned, you can use indices to retrieve the values (as in the 2nd example). And in case, You want to use indices to assign values, first declare the size of the array (as in the edited version)!
the default constructor (that is called here: vector<int> multiples_of_three;) creates an empty vector. you can populate them with push_back or better if you know the number of objects you have to add, pass that number to the constructor, so it reserves the required amount of memory at once instead of constantly growing (that means allocating memory and copying the old menory into the new) the vector.
another alternative is to call reserve from the empty default contructed vector and use push_back to populate it. reserve reserves enough memory to keep the required amount of objects but without changing the size of the vector. advantage of reserve is that the default constructor is not called for every object (as it will be done with resize or parameterized constructor) that would be not necessary since you overwrite the the object in your initialization loop right after the creation of the vector.
You need to use push_back() rather than add via the indexer.
The indexer can be used for read/write access to a vector only within the bounds.
A vector doesn't magically grow in size because you use []. It started out with 0 elements in the first example and you never grew it.

Is it possible to print vector content with width of 5?

Here is what I have to do!
Write a program to perform the following steps.
Allocate memory dynamically to store an array of 10 ints.
Assign each int a random value between 1 and 100.
Copy each of the 10 random ints to a vector of ints.
Print the dynamically allocated array of ints and the vector of ints, each with a width of 5, as shown in the sample output below.
I have trouble with the last point. My code is working perfectly, but I don't know how to set width in vector of ints so it is the same as array of ints.
#include<iostream>
#include<iomanip>
#include<cstdlib>
#include <vector>
#include <algorithm>
#include <iterator>
#include <stdexcept>
using namespace std;
int main(){
const int SIZE = 10;
int *arr = new int[SIZE];
//assign rand numbers between 0 and 100
for (int i = 0; i < SIZE; ++i){
*(arr + i) = rand() % 100+1;
}
//print array
for (int i = 0; i < SIZE; ++i){
cout << setw(5) << *(arr +i) << " ";
}
std::vector<int> integers (arr, arr + 10);
std::ostream_iterator<int> output(cout, " ");
cout << endl;
cout << "Vector integers contain: " << endl;
std::copy(integers.begin(), integers.end(), output);
return 0;
}
Your code works fine as is. cout << setw(5); sets the width just fine. You could also use cout.width(5);.
If you really want to do this with an ostream_iterator, the cleanest way is probably with a small proxy class:
class integer {
int i;
public:
integer(int i) : i(i) {}
friend std::ostream &operator<<(std::ostream &os, integer i) {
return os << std::setw(5) < i.i;
}
};
Then to write them out, use that type as the template parameter to the ostream_iterator:
std::copy(integers.begin(), integers.end(),
std::ostream_iterator<integer>(std::cout, ' '));
This will create a temporary integer object, then write it out using the operator<< for integer, which sets the width. At least in theory, this probably imposes some overhead, but I'd expect (at least with optimization enabled) most compilers will probably see through the subterfuge (so to speak) and eliminate any extra copies and such.
Of course, if the width isn't cast in concrete, you could make integer a template, and supply the width as a template parameter:
template <int N>
class integer {
// ...
return os << std::setw(N) < i.i;
Unless I really needed to use an ostream_iterator, I think I'd use a range-based for loop though:
for (int i : integers)
std::cout << std::setw(5) << i << ' ';
Since the width of a stream is reset to 0 everytime it is used, you can't use a std::ostream_iterator<int> (well, you could by using a custom std::num_get<char> facet which restores the width but that seems a bit radical).
You can print the std::vector<int> like this, however:
std::for_each(integers.begin(), integers.end(),
[](int v){ std::cout << std::setw(5) << v << ' '; });

Array of int or vector?

i'm trying to store some elements that is going to change every time, but i don't know which
way is better and why. I'm thinking about two ways, 1) declaring array of int and loop or
use vector's.
Which way is better and why?
Does declaring array of int have any future memore problems as leak?
the code down below show the two ways i'm talking about:
1)
#include <iostream>
#include <vector>
int main()
{
int x[5];
x[0] = 10;
x[1] = 20;
x[2] = 30;
x[3] = 40;
x[4] = 50;
for(unsigned int i = 0;i<=sizeof(x[5]); i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
2)
#include <iostream>
#include <vector>
int main()
{
std::vector<int> x;
x.push_back(10);
x.push_back(20);
x.push_back(30);
x.push_back(40);
x.push_back(50);
for(unsigned int i = 0;i<=x.size()-1; i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
If this is all you have to do, and your array will always have a size that is known at compile time, then you do not need std::vector.
On the other hand, in C++11 you could use std::array instead of a plain C array (std::array is a zero-overhead, safer and more functional wrapper over a C array):
#include <iostream>
#include <array>
int main()
{
std::array<int, 5> x = { 10, 20, 30, 40, 50 };
for (unsigned int i = 0; i < x.size(); i++)
// ^^^^^^^^
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
}
Here is a live example. Notice, that std::array offers a size() member function which you may want to use instead of the sizeof operator.
Moreover, since std::array is a standard sequence container, you could iterate through its element this way:
std::size_t i = 0;
for (auto e : x)
{
std:: cout << "x[" << i++ << "] = "<< e << std::endl;
}
Here is a live example.
If the size is known at compile time, use std::array. If not, use std::vector. In either case, use iterators to look at the elements:
typedef std::array<int> my_container_type;
typedef my_container::iterator iterator;
my_container_type my_container = { whatever };
for (iterator it = my_container.begin(); it != my_container.end(); ++it)
std::cout << "x[" << (it - my_container.begin()) << "] = " << *it << '\n';
By using iterators you greatly reduce the risk of accidentally using a loop limit like sizeof(x[5]), which is nonsense.
Neither is "better". They both address entirely different use cases.
If you know the array size at compile time and are 100% sure it will never change, sure, use a plain old array. It has less overhead, and the compiler can even aid you with static analysis by spotting any attempts to read outside the boundaries.
On the other hand, if you are unsure of the array's side (i.e. you will be reading input from a file or the user), then use the std::vector. It can grow to any size to meet your needs.

Trying to initialize a list with values but not working when I use a variable to create the size

This is my second time using C++ and I'm trying to port some Java code I made but am having trouble understanding some behavior. I have a list of data and want to create another list of the same size but the values are default to zero(in Java I use Arrays.fill(list, 0); after creating it). When I try to do something similar in C++ I get variable-sized object 'list1' may not be initialized
Here's a code to better example:
#include <iostream>
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace std;
using namespace boost::assign;
int main()
{
cout << "Hello World!" << endl;
vector<short> data;
data += -40, -30,-10, 20, 50;
//int coeff [data.size()];
cout << "data array size is " << data.size() << endl;
short list1 [data.size()] = {0}; //does not work
for (int i =0; i<data.size(); i++) {
cout << "data is " << list1[i] << endl;
}
cout << "********** try 2 **************" << endl;
//this works if I use a actual number to create the list but I want to declare it at runtime
short list2 [5] = {0};
for (int ii=0;ii<5;ii++) {
cout << "data is " << list2[ii] << endl;
}
return 0;
}
Like I mentioned, I'm completely green when I comes to C++ (I have read a book and done a few tutorials) so I may be doing something completely wrong. In the event I cannot do this at runtime and only at compile time, is there something else I can use to get the same result?
c++ does not have dynamically sized arrays, so this is illegal:
short list1 [data.size()];
but you can use a vector:
std::vector<short> list1(data.size(),0);
That creates a vector of the same length as data, full of zeroes.
If you want an array whose size is determined at runtime, you'll have to allocate it.
short * list1 = new short[data.size()];
//do stuff
delete [] list1; //we don't want to leak
You typically want to avoid naked pointers whenever possible, so the cleaner solution is what juanchopanza suggested and try to use std::vector.
The equivalent of Arrays.fill(list, 0); for a C++ vector looks like std::fill(list.begin(), list.end(), 0);
You can also simply declare a std::vector<short> list1(data.size()); to create it with zero initialized values or with a specific value std::vector<short> list1(data.size(), 0);