So I'm pretty sure it's having issues because it's trying to print the pointer instead of the value, but I don't know how to fix it.
class cName {
private:
std::vector< std::vector<int>> *vect2d;
public:
// initializes vector that contains x number of vectors
// that each contain y number of ints
cName(int x,int y);
void printVector(int);
}
void cName::printVector(int x) {
for(int i=0; i<x; i++) {
//have to get size because
// the number of ints in the vector will change
for(int j=0; j< this->vect2d[i].size(); j++)
std::cout << this->vect2d[i][j]<<" ";
std::cout<<"\n";
}
}
I'm having issues printing a 2d vector I use in a class I'm making. I get an error that says:
cannot bind 'std::ostream {aka std::basic_ostream<char>'
lvalue to 'std::basic_ostream<char>&&'
Question:
Could someone explain me why is throwing me that error and help me fix it?
The vect2d member is a pointer to a vector of vectors of ints. You don't really need a pointer here, just use a vector of vectors of ints.
Your usage of this pointer does not produce any immediate errors because the subscript operator array[index] can be used on pointers. If you are not sure that your code is correct, prefer to use the range-checked .at(index) method for std::vector instances. Using an explicit method would have pointed you to your error, since there is no .at(index) method for pointers.
What the compiler currently sees when you call this->vect2d[i].size() is:
this->vect2d of type vector<vector<int>>*, a complicated way of spelling vect2d. Note that this is a pointer type.
this->vect2d[i] of type vector<vector<int>>, which is equivalent to *(vect2d + i), but not to (*vect2d)[i] or vect2d->at(i)! Note that this is not a pointer type, but still two nested vectors.
Therefore, the .size() is called on the vector that is i vector sizes away from your outer *vect2d container. Quite likely, this is invalid memory and could segfault.
When you later do vect2d[i][j], that is actually equivalent to *(vect2d + i)[j] which should behave the same as (vect2d + i)->at(j). But it is not vect2d->at(i).at(j)! Notably, it is of type vector<int> rather than int. That is the cause of your error message: there's no available operator<< to print vectors, so the compiler produces that quite incomprehensible error.
Related
In the case I am creating an 'array' on stack in c++, is it better to initialise an empty vector with a reserved number of elements and then pass this to a function like foo() as a reference as below. Or is it better to set an array arrb of size nelems, then using a pointer p_arrb to the address of the first element increment the pointer and assign some value?
#include <iostream>
#include <vector>
void foo(std::vector<int>& arr){
int nelems = arr.capacity();
for (int i = 0; i < nelems; i++){
arr[i] = i;
}
}
int main()
{
int nelems;
std::cout << "Type a number: "; // Type a number and press enter
std::cin >> nelems;
std::vector<int> arr;
arr.reserve(nelems); // Init std lib vector
foo(arr);
int arrb[nelems];
int* p_arrb = &(arrb[0]); // pointer to arrb
for (int i = 0; i < nelems; i ++){
*(p_arrb++) = i; // populate using pointer
}
p_arrb -= nelems; // decrement pointer
return 0;
}
It seems people prefer the use of vector as it is standardised and easier to read? Apart from that, is there any performance benefit to using vector instead of a basic pointer in this case where I do not need to change the size of my vector/array at any point in the code?
What you should use depends on the exact goal you have. In general the best approach is to avoid using "raw arrays" (both dynamic and static) wherever possible.
If you need dynamic array, use std::vector. If you need static array, use std::array.
You can't use the arrb variant because the size of an array must be a compile-time constant in C++, but you are trying to use a runtime size here.
If your compiler is compiling this, then it is doing so only because it supports these so-called variable-length arrays as a non-standard extension. Other compilers will not support them or have differing degree of support or behavior. These arrays are optionally-supported in C, but even there they are probably not worth the trouble they cause.
There is no way to allocate a runtime-dependent amount of memory on the stack in C++ (except if you misuse recursive function calls to simulate it).
So yes, you should use the vector approach. But as discussed in the comments under the question, what you are doing is wrong and causes undefined behavior. You need to either reserve memory and then emplace_back/push_back elements into the vector or you need to resize the vector to the expected size and then you may index it directly. Indexing a vector outside the the range of elements already created in it causes undefined behavior.
I have a 2D array a[][40]. I'm trying to sort it by calling std::sort, and I have written the Compare function. However, C++ wants me to have a std::vector to be sorted, not a simple array and I want the sorted array to be a itself, I don't want to create another array and save the sorting result there. It seems there are a lot of ways to achieve that. I could think of five ways, but none of them seems to be efficient and working.
1)
Directly use std::sort(std::begin(a), std::begin(a) + something, cmp);
It doesn't work, because std::begin doesn't know how to point to the beginning of a 2D array. Furthermore, it'd sort incorrectly even if it compiled, since a 2D array is not an array of references to arrays, but consecutive arrays (unlike Java)
Playground: https://godbolt.org/g/1tu3TF
2)
std::vector<unsigned char[40]> k(a, a + x);
std::sort(k.begin(), k.end(), cmp);
Then copy everything back to a
It doesn't work, because it's a 2D array, and it can't be sorted this way, using std::sort. In contrast to the first trial, this one uses twice as much as memory, and copies everything twice (if it worked)!
Playground: https://godbolt.org/g/TgCT6Z
3)
std::vector<int> k(x);
for (int i = 0; i < x; k[i] = i, i++);
std::sort(k.begin(), k.end(), cmp2);
Then change the order of a to be the same of k;
The idea is simple, create a vector of representative "pointers", sort them (as the cmp2 function secretly accesses a and compares the values), then make a have the same order with k.
In the end, the re-ordering loop will be very complex, will require a large, temporary variable. Besides, for cmp2 to access the values of a, a global variable-pointer that points to a must be created, which is "bad" code.
Playground: https://godbolt.org/g/EjdMo7
4)
For all unsigned char[40], a struct can be created and their values can be copied to structs. Comparison and = operators will need to be declared. After sorted, they can be copied back to a.
It'd be a great solution if the arrays didn't have to be copied to structs to use struct's operators, but they need to be copied, so all values will be copied twice, and twice-as-needed memory will be used.
5)
For all unsigned char[40], a struct that has a pointer to them can be created. They can be sorted by the pointed values, and the result can be saved to a pointer array.
It's probably the best option, although the result is a pointer array instead a. Another reason on why it's good is it doesn't move the arrays, but the pointers.
To sum up, I need to sort the 2D array a[][40] via std::sort, but I haven't decided on the best way. It seems there's a "best way to do that" which I can't think of. Could you please help me?
EDIT: To clarify, I want {{3,2}{1,4}} to become {{1,4}{3,2}}
The problem is not in iterating a 2D array. Provided the columns size is a constexpr value, pointers to arrays are nice iterators.
But all C++ sort (or mutating) algorithms require the underlying type to be move constructible and move assignable and an array is not assignable. But wrapping the underlying arrays can be enough:
template <class T, int sz>
class wrapper {
T* base;
bool own; // a trick to allow temporaries: only them have own == true
public:
// constructor using a existing array
wrapper(T* arr): base(arr), own(false) {}
~wrapper() { // destructor
if (own) {
delete[] base; // destruct array for a temporary wrapper
}
}
// move constructor - in fact copy to a temporary array
wrapper(wrapper<T, sz>&& src): base(new T[sz]), own(true) {
for(int i=0; i<sz; i++) {
base[i] = src.base[i];
}
}
// move assignment operator - in fact also copy
wrapper<T, sz>& operator = (wrapper<T, sz>&& src) {
for(int i=0; i<sz; i++) {
base[i] = src.base[i];
}
return *this;
}
// native ordering based on lexicographic string order
bool operator < (const wrapper<T, sz>& other) const {
return std::char_traits<char>::compare(base, other.base, sz) < 0;
}
const T* value() const { // access to the underlying string for tests
return base;
}
};
Then, you can sort a C compatible 2D array with any C++ sort algo:
std::vector<wrapper<char, 40> > v { &arr[0], &arr[sz] }; // pointer are iterators...
std::sort(v.begin(), v.end()); // and that's all!
for (int i=0; i<sz; i++) { // control
std::cout << arr[i] << std::endl;
}
The overhead is a vector of structures containing a pointer and a bool, but what is sorted is actually the original 2D array.
Of course, as the C library is accessible from C++, qsort would certainly be easier for sorting a C compatible 2D array. But this way allows the use of stable_sort or partial_sort if they are relevant.
I'm new to using C++ for complicated programming. I've been sifting through some leftover, uncommented, academic code handed down through my department, and I've stumbled across something I have no real idea how to google for. I don't understand the syntax in referencing an array of structs.
Here is a trimmed version of what I'm struggling with:
typedef struct
{
double x0,y0;
double r;
} circle;
double foo()
{
int N = 3;
double mtt;
circle circles[N];
for (int i = 0; i < N; i++)
{
mtt += mtt_call_func((circles+i), N);
}
return mtt;
}
What does (circles+i) mean in this case?
EDIT: the function should have (circles + i), not (circle + i).
circles+i is equivalent to &circles[i]. That's how pointer arithmetic works in C++.
Why is there a pointer? Well, when you give the name of an array, in a context other than &circles or sizeof circles, a temporary pointer is created that points to the first member of the array; that's what your code works with. Arrays are second-class citizens in C++; they don't behave like objects.
(I'm assuming your circle+i was a typo for circles+i as the others suggested)
circle+i means "take a pointer circle and move it i times by the size of the object pointed to by it". Pointer is involved because the name of the array is a pointer to it's first element.
Apart from this you should initialize an integer counter variable that is used in loop:
for (int i = 0; i < N; i++)
^^^^
{
mtt += mtt_call_func( ( circles + i), N);
^ // typo
}
In C, as in C++, it is legal to treat an array as a pointer. So circles+i adds i times the size of circle to the address of circles.
It might be clearer to write &circles[i]; in this form, it is more obvious that the expression produces a pointer to the ith struct in the array.
Each vector you declare in stack it's actually a pointer to the first index, 0, of the vector. Using i you move from index to index. As result, (circles+i) it's the equivalent of &circles[i].
& means the address of the variable. As in your function call, you send a pointer which stores an address of a variable, therefore & is required in front of circles[i] if you were to change to that, as you need the address of the i index of the vector circles to run your function.
For more about pointers, vectors and structures check this out: http://pw1.netcom.com/~tjensen/ptr/pointers.htm
It should cover you through ground basics.
I am trying to create an array that generates random values, then assign a pointer to that array in order to use it in other functions.
Question 1: Is this the right approach?
Question 2: When I run the code below, my pointer function generates values inconsistent with what the actual array's value is. What am I doing wrong?
int size = 100;
int theray[size];
for(int i=0; i<size; i++)
{
theray[i] = (rand()%100);
}
//Output array
cout<<"The array: ";
for(int j=0; j<size; j++)
{
cout<<theray[j]<<" ";
}
cout<<endl;
int (*parray)[100] = &theray;
cout<<"The array pointer: ";
for(int k=0; k<size; k++)
{
cout<<*parray[k]<<" ";
}
Question 1: is this the right approach?
No. The right approach is to use std::vector<int> if size is not known at compile time1, and std::array<int, size> if it is2. There is no need for pointers here.
void foo(const std::vector<int>& v)
{
// do stuff with v
}
...
std::vector<int> v(size); // vector with size elements
// do something with v
// pass v to a function
foo(v);
Question 2: when I run the code below, my pointer function generates values inconsistent with what the actual array's value is. What am I doing wrong?
If you use C++ idioms you won't even encounter this problem, so I consider the question moot. However, in your case you have a problem of operator precedence: be explicit about applying de-reference * before access []:
cout<< (*parray)[k] << " ";
1 As shown in the example, you can use an std::vector as a fixed size array, where the size need not be known at runtime. Just bear in mind that it is possible to change it's size after construction.
2In your example, size is not a compile time constant so you cannot use std::array. However, if you had declared it as const int size = 100; then it would be considered a compile time constant.
Your code is a bit off in three ways. First, there is no need to use &theray. Array names already reference a memory address. You can simply assign the pointer to theray. Second, you're declaring an array of 100 pointers. Based on your description, it sounds like you just want one pointer that points to the array. Your declaration should just be int *parray instead of int *parray [100]. Finally, once you have a pointer to the array, you can access elements of the array the same way you would with the original array, only with the name of the pointer, instead of the name of the array. Try changing your last block of code (starting with the pointer declaration to this:
int *parray;
parray = theray;
cout<<"The array pointer: ";
for(int k=0; k<size; k++)
{
cout<<parray[k]<<" ";
}
Question 1
Is this the right approach?
Usually not. It depends on what you are trying to achieve.
For high level semantics you'd in most cases use std::vector<int> or, if the size is fixed and you are using C++11, std::array<int, size>. If you actually have to go down to the pointer level, you'd usually write it like this:
int *parray = theray;
cout<<"The array pointer: ";
for(int k=0; k<size; k++)
{
cout<<parray[k]<<" ";
}
This works because arrays will degrade to pointers, and the […] subscripts work on these pointers just like they work on the original arrays.
Question 2
When I run the code below, my pointer function generates values inconsistent with what the actual array's value is, what am I doing wrong?
*parray[k] gets interpreted as *(parray[k]) while you intend to use it as (*parray)[k].
Question 1: is this the right approach?
No. Use std::vector<> for arrays whose size can change dynamically (at run-time). Prefer avoiding pointers and manual memory management.
Question 2: when I run the code below, my pointer function generates values inconsistent with what the actual array's value is. What am I doing wrong?
First of all, the fact of creating pointers so you can pass the array to a function. This is not necessary. Here is how I would use classes from the C++ Standard Library to write that program (in C++11):
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
// Sample function that prints the vectors's content
void foo(std::vector<int> const& v)
{
copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, " "));
}
int main()
{
// Populate the vector...
size_t sz = 10;
std::vector<int> v(sz);
generate(begin(v), end(v), [] () { return rand() % 100; });
// Pass it to a function...
foo(v);
}
In using Dev C++, I a m trying to insert a smaller 2D array object into a larger 2D array object. While attempting to achieve that, I came into compilers errors which I do not know how to solve.
I attempt to insert the smaller Object by making it returning the array's name. Then I attempt to change the values inside the large array with the values of the smaller array.
There two line of code that I have problems with:
int result = smallerArray.extractPiece();
largerArray.extractArray(result);
And within these two lines of codes:
int Piece::extractPiece()
{
return **pieceArray;
}
and
void Grid::extractArray( int** arr )
{
for(int i = 0; i < xGrid ; ++i)
{
for (int j = 0; j < yGrid ; ++j)
{
squares[i][j] = arr[i][j];
}
}
}
The two of the problems is that "int result" will not hold smallerArray.extractPiece(),
and if i just put "smallerArray.extractPiece()" in largerArray.extractArray(), i still get problems. I attempted to make "int result" a pointer pointer, as "int** result", i still have the same errors.
These are the errors that i get when i try to compile in Dev C++:
In function `int main()';
invalid conversion from `int' to `int**'
initlizing argument 1 of 'void Grid::extractArray(int**)'
[Build Error] [grid test.o] Error 1
Does anyone know whats wrong?
It's precisely this bunch of code:
int result = smallerArray.extractPiece();
largerArray.extractArray(result);
// ...
int Piece::extractPiece() {
return **pieceArray;
}
Trying to pass an int to extractArray, which wants a pointer to a pointer, presumable your dynamic array, and not an int. Try changing it to
int **result = smallerArray.extractPiece();
largerArray.extractArray(result);
// ...
int ** Piece::extractPiece() {
return pieceArray;
}
Only changing result to a pointer to pointer won't work. You of course also have to change what extractPiece returns (changing from int to int**)
Look, always at least for me it was easier to manage 2D arrays internally as 1D arrays where M[i,j]=A[i*N+j] where N is the number of cols (or rows, if the 2D arrays is row-column type). Users may get elements with the i,j indices but my class always store A[M * N] as private data. Passing 1-D pointer arrays is easier than managing 2-D pointer arrays (you can't fall in the pointer-to-pointer syntax which can get messy in some code).,
This is not related to this question, but since I don't know about specific compiler optimization instrinsics, I wonder if M[i,j] gets transformed to A[i] internally to use simpler addressing modes in the generated code.