Can vectors share the same memory space? - c++

Consider this program:
#include <vector>
#include <iostream>
using std::vector;
int main(){
vector<vector<double>> A; A.reserve(3);
vector<double> row1 = {0, 0, 5};
vector<double> row2 = {0, -3, 0};
vector<double> row3 = {1.5, 0, 0};
A.push_back(row1); A.push_back(std::move(row2)); A.push_back(row3);
for (int i = 0 ; i < 3 ; i++){
for (int j = 0 ; j < 3 ; j++){
std::printf("%-7.2f", A[i][j]);
}
std::cout << std::endl;
}
std::cout << std::endl;
}
In the Xcode debugger, it's easy to see that by the time the for loop is reached, row2 is empty (it's contents 'stolen' by std::move), whereas row1 and row3 were only copied, and still maintain their values.
My question is exactly this: does the object A[0] point to the exact same memory location that row1 points to at this point? In other words, is row1's contents in a copy-on-write state, where as soon as either row1 or A[0] modify their contents a copy is created, but in the meantime, they share the memory containing {0, 0, 5} and there is nothing additional allocated.
I am asking this because I am computing the determinant of a matrix, passing in a const std::vector<std::vector<double>> &, and I don't want any additional memory used, but rather, the memory of that object itself.

Related

How to write multiple vectors to multidimensional array?

I have 2 vectors of ints:
vector<int> even = {2, 4, 6, 8};
vector<int> odd = {1, 3, 5, 7, 9};
I am trying to pass these vectors into a 2d array so that they end up looking like this:
array[2][5] = {2, 4, 6, 8,
1, 3, 5, 7, 9};
Writing a function to do this but I cant get it to work, this is the code so far:
void copy(vector<int> even, vector<int> odd,int arr[][COLMAX]){
int vectors = 2;
for(int row = 0; row < vectors; row++){
for(int col = 0; col < even.size(); col++){
arr[row][col] = even[col];
}
cout << endl;
}
}
Edit: Added function code
Here is one way:
void copy(vector<int> even, vector<int> odd,int arr[][COLMAX]){
for(int col = 0; col < even.size(); col++){
arr[0][col] = even[col];
}
for(int col = 0; col < odd.size(); col++){
arr[1][col] = odd[col];
}
}
Why go for arrays if you can use vectors?
If you can use a 2D vector instead of a 2D array, you'd have much more flexibility. And it'll be very simple:
vector<int> even = {2, 4, 6, 8};
vector<int> odd = {1, 3, 5, 7, 9};
vector<vector<int>> v {even,odd}; // that's sufficient !!
for (auto &r: v) { // and this is only the printing of the results
std::copy(r.cbegin(), r.cend(), ostream_iterator<int>(cout," "));
cout <<endl;
}
If you must really use raw arrays...
Now if you really want to use fixed size 2D arrays, you can update your function:
const size_t COLMAX=10;
void mycopy(vector<int> even, vector<int> odd,int arr[][COLMAX]){
vector<const vector<int> *>v ={&even,&odd};
for(int row=0; row<v.size(); row++) {
for(int col = 0; col <COLMAX; col++){
arr[row][col] = (col < v[row]->size() ? (*v[row])[col]:0);
}
}
}
It uses a pointer to the vectors to avoid repeating several time the same code for the different vectors. Moreover, you could easily make it work for 3 or 4 vecotrs (and with a little imagination you could eaily adapt it for a variable number of arguments).
You can then use it as planned:
int myarr[2][COLMAX];
mycopy (even, odd, myarr);
for (int i=0; i<2; i++) {
std::copy (myarr[i], myarr[i]+COLMAX, ostream_iterator<int>(cout," "));
cout <<endl;
}
The problem is that you do not keep track of the number of elements that are really in each line, so you'd have either al lot of truncated lines, or lines with a lot of trailing zeroes.

Create a two 2d array of pointers based on the same data

I was trying create a 2d array of pointers based on other. Here is a base 2d array:
double **a = new double*[3];
a[0] = new double[3]{ 1, 2, 3 };
a[1] = new double[3]{ 4, 5, 6 };
a[2] = new double[3]{ 7, 8, 9 };
And I want create a 2x2 matrix which should look like this:
5,6
8,9
Finally, I was trying resolve the problem as follow:
double **b = &a[1];
b[0] = a[1];
b[1] = a[2];
Unfortunately, this code does not work as I expect. In addition, I would like to get access to data using negative indices eg. b[-1][-1] should return 1 value.
With:
double a0[] = { 1, 2, 3 };
double a1[] = { 4, 5, 6 };
double a2[] = { 7, 8, 9 };
double* b0[3] = {&a0[1], &a1[1], &a2[1]};
double** b = &b0[1];
you can access with negative index and do:
for (int i = -1; i != 2; ++i) {
for (int j = -1; j != 2; ++j) {
std::cout << b[i][j] << std::endl;
}
}
This approach cannot work. One property of this kind of 2d array is that &A[k+1] = &A[k]+1, but that relationship does not hold between your desired B[0] and B[1], because those are actually &A[1][1] and &A[2][1], which could be miles apart.
What your code actually does is:
double **b = &a[1]; // all right, b points to part of a[]
b[0] = a[1]; // this assignment does nothing, they're already equal
b[1] = a[2]; // this assignment does nothing, they're already equal
This might help you out some and get you on the right track.
#include <conio.h>
#include <iostream>
struct Vec3 {
union {
double d3[3];
struct {
double x;
double y;
double z;
};
};
double& operator[]( int idx );
};
double& Vec3::operator[]( int idx ) {
return d3[idx];
}
typedef Vec3 Row;
struct Matrix {
union {
Row r[3];
struct {
Row row1;
Row row2;
Row row3;
};
};
Row& operator[]( int idx );
};
Row& Matrix::operator[]( int idx ) {
return r[idx];
}
int main() {
Matrix m;
m.row1.x = 1;
m.row1.y = 2;
m.row1.z = 3;
m.row2.x = 4;
m.row2.y = 5;
m.row2.z = 6;
m.row3.x = 7;
m.row3.y = 8;
m.row3.z = 9;
for ( int i = 0; i < 3; i++ ) {
for ( int j = 0; j < 3; j++ ) {
m[i][j] += 10;
std::cout << m[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
I did not add any error checking or bounds checking into the overloaded operator I just allowed the user to pass any value into it. This you would have to design to your specific needs. I'm just demonstrating an easy way to create a 2D Array or a Matrix like object using unions to have quick access to the subscript or bracket operator. I show a sample use of creating a 3x3 matrix with each value ranging from 1-9 then I use a double for loop to add 10 to each value then print out the new value within the array using the double brackets. This is all done on the stack which is better then using pointers and creating new memory for each place. If you need to use the heap then you could just assign this matrix class its own pointer and create it on the heap instead of every individual element. Another thing that can be done with this is if you need to use this for say int, float or some other data type you can easily template this class or structure.
As for indexing by a negative value; I have not heard of anyone doing so. This isn't to say that it can not be done, but from what I recall on how pointers & arrays behave with indexing according to their association with memory addressing they are 0 based index. This usually means that if we have a memory block a pointer to a double type variable, this usually means that each block of memory in most cases is 8 bytes wide. The very first element resides in the very first memory address location that is assigned to this variable for both the stack and the heap. If you try to use negative numbers which involve pointer arithmetic you begin to traverse memory that doesn't belong to this declared variable. To try and pull off what you are suggesting might require more than just basic C/C++ code can do, you might have to dive into asm to get something like this to work, especially if you want to avoid using if statements within the overloaded operators.

Sorting one array based on another in place [duplicate]

This question already has answers here:
Sorting zipped (locked) containers in C++ using boost or the STL
(5 answers)
Closed 7 years ago.
I'm coding in C++ (with c++11 standards) and I have two big arrays of built-in type that I want to sort the second one based on the first.
here is an example:
A = {1, 5, 4, 3, 6, 2};
B = {1, 2, 3, 4, 5, 6};
after sorting:
A = {1, 2, 3, 4, 5, 6};
B = {1, 6, 4, 3, 2, 5};
It's as if each element B[i] is attached to element A[i] and you just sort array A. So elements in B move according the corresponding element in A. I know this questions has been asked over and over, yet the only solution I've come across with is to use pair<type 1, type 2>. But considering the arrays are big, it takes quite a while to allocate the memory for pairs array and copy arrays back and forth.
But I believe the sorting can be done in-place, i.e., using only O(1) memory. In fact if std::sort allowed for costume swap it would have been fine. Because I assume that's the only thing beyond comparator that sorting algorithms use.
A = vector<double>(1e6); // some random numbers
B = vector<double>(1e6); // some random numbers
Comp comp(&A,&B);
Swap swap(&A,&B);
costume_sort(A,B,comp,swap); // some sort function that can take costume swap and compare
class Comp {
vector<double> *A;
vector<double> *B;
Comp(vector<double> *A, vector<double> *B) : A(A),B(B) {};
bool compareTo(size_t i, size_t j) { return A->at(i) < A->at(j); };
};
class Swap {
vector<double> *A;
vector<double> *B;
Swap(vector<double> *A, vector<double> *B) : A(A),B(B) {};
void swapFnc(size_t i, size_t j) { swap(A->at(i), A->at(j));swap(B->at(i), B->at(j)); };
};
Is there any function in STL or other libraries available that can do that? This is a sort of pseudo-code of the idea I'm trying to explain here. Obviously it's not precise but I hope it's clear what I mean.
You can sort based on indices similar to the related post: std::sort and custom swap function.
It is not a custom swap function and allocateds some more memory, but should perform well.
If you are defining the types, then you can overload std::swap to do what you want: How to overload std::swap().
No there is not an std:: function that meets your requirements.
Although it's possible to provide its custom comparison (so Q&A) and swap (so Q&A) functor, those take a (constant) reference to the items to compare or swap, not an index on an hypothetical container. Indeed those functors should have meaning for comparisons and swaps of non-contained objects.
Example of reorder a[] and b[] in place according to a sorted array of pointers to a[]. Since an array of pointers is used, the compare function only needs to know the type of elements being compared. The reorder in place code time complexity is O(n), every store places a value in its sorted location. Note that the array of pointers is restored to it's original state (&a[0] ... &a[n-1]) during the reorder.
bool compare(const int *p0, const int *p1)
{
return *p0 < *p1;
}
int main()
{
int a[8] = {7,5,0,6,4,2,3,1};
char b[8] = {'h','f','a','g','e','c','d','b'};
int *pa[8];
size_t i, j, k;
int ta;
char tb;
// create array of pointers to a[]
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
pa[i] = &a[i];
// sort array of pointers to a[]
std::sort(pa, pa+sizeof(a)/sizeof(a[0]), compare);
// reorder a[] and b[] according to the array of pointers to a[]
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++){
if(i != pa[i]-a){
ta = a[i];
tb = b[i];
k = i;
while(i != (j = pa[k]-a)){
a[k] = a[j];
b[k] = b[j];
pa[k] = &a[k];
k = j;
}
a[k] = ta;
b[k] = tb;
pa[k] = &a[k];
}
}
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
std::cout << a[i] << ' ';
std::cout << std::endl;
for(i = 0; i < sizeof(b)/sizeof(b[0]); i++)
std::cout << b[i] << ' ';
std::cout << std::endl;
return 0;
}

Concatenation of vectors [duplicate]

This question already has answers here:
Appending a vector to a vector [duplicate]
(4 answers)
Closed 9 years ago.
My apologies for the title, I did not know of a better one.
So, basically, I have a 1D vector, which I extract 256 pieces of data from this, until there is no more data left.
std::size_t begin = 0;
std::size_t nextEnd = 0;
while (nextEnd < signal.size()) {
begin = nextEnd;
nextEnd += 256;
Transform(signal, begin, std::min(nextEnd, signal.size()));
}
Inside the "Transform" function, there is a new, temp vector created called temp_vector and inside my main I have a global 1D vector.
What I want to do is, every iteration of this loop, the values of the temp_vector is pushed back into the global 1D vector at the right position.
So for example:
std::vector<double> global;
std::vector<double> actual = {1,1,0,0,2, 3, 4 ....., n};
// here loop over n number of elements
// TRANSFORM:
// std::vector<double> temp_vector = {10, 50}; // after calculations
// global.push_back(temp_vector);
So at the end result, the global_vector will still be a 1D vector, however, will contain all of the values, in the same place for each of the elements.
I hope I have explained myself enough!
Here is code for array merging:
#include <vector>
#include <iostream>
int main() {
std::vector<int> glob = {1, 2, 3};
std::vector<int> temp_vector = {4, 5, 6};
glob.insert(glob.end(), temp_vector.begin(), temp_vector.end());
std::vector<int>::const_iterator it = glob.begin();
for(; it != glob.end(); ++it) {
std::cout << *it << ", ";
}
return 0;
}
Output:
./a.out
1, 2, 3, 4, 5, 6,
Consider to use an ordered container like std::set or std::priority_queue and insert into that container directly, not using a temporary.

How to get column of a multidimensional array in C/C++?

int matrix[9][9],*p;
p=matrix[0];
this works and gives first row of matrix, but how to get first column of matrix I've tried p=matrix[][0]; ? Also I don't understand why below code gets compiler error ?
int matrix[9][9],p[9]; // it looks really ugly, byt why it doesn't work ?
p=matrix[0]; // compiler gives "invalid array assigment"
is it because multidimensional arrays are arrays of arrays - and we should interpret matrix[i][j] as j-th element of i-th nested array ?
In C/C++, multidimensional arrays are actually stored as one dimensional arrays (in the memory). Your 2D matrix is stored as a one dimensional array with row-first ordering. That is why getting a column out of it is not easy, and not provided by default. There is no contiguous array in the memory that you can get a pointer to which represents a column of a multidimensional array. See below:
When you do p=matrix[0], you are just getting the pointer to the first element matrix[0][0], and that makes you think that you got the pointer to first row. Actually, it is a pointer to the entire contiguous array that holds matrix, as follows:
matrix[0][0]
matrix[0][1]
matrix[0][2]
.
.
matrix[1][0]
matrix[1][1]
matrix[1][2]
.
.
matrix[8][0]
matrix[8][1]
matrix[8][2]
.
.
matrix[8][8]
As seen above, the elements of any given column are separated by other elements in the corresponding rows.
So, as a side note, with pointer p, you can walk through the entire 81 elements of your matrix if you wanted to.
You can get the first column using a loop like
for(int i = 0; i < 9; i++)
{
printf("Element %d: %d", i, matrix[i][0]);
}
I think the assignment doesn't work properly because you're trying to assign something's that's not an address to a pointer.
(Sorry this is c code)
There is no difference between specifying matrix[81] or matrix[9][9]
matrix[r][c] simply means the same as matrix[9*r+c]
There are other containers better suited fort multidimensional arrays like boost::multi_array
http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/index.html
Think of the bare array just like allocating a contiguous piece of memory. You, the programmer then has to handle this piece of memory yourself. The bare name of the array, e.g. matrix is a pointer to the first element of this allocated piece of memory. Then *(matrix+1) is the same as matrix[0][1] or matrix[1].
p is an array of int, matrix[0] is a pointer..
matrix itself is the nearest thing you can get to a column of the array, inasmuch as (matrix + 1)[0][0] is the same as matrix[1][0].
Here's a program which builds a 10x10 array and prints the second column:
#include <iostream>
using namespace std;
int main()
{
int aa[10][10];
for(int i = 0; i<10; i++)
for(int j = 0; j<10; j++)
aa[i][j] = i*10+j;
int col = 2;
// pointer to a length-10 1d array
int (*p)[10] = (int (*)[10])&(aa[0][col]);
for(int i =0; i<10; i++)
cout << *(p[i]) << endl;
return 0;
}
The difference from aa[row][2] is using a pointer to a length-10 1d int array int (*p)[10], For more context about int (*p)[10], see this answer
p saves the address of 1d array {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
. And p+1 saves the address of 1d array {12, 13, 14, 15, 16, 17, 18, 19, 20, 21}. *(p[1]) or *(*(p+1)) access the first value of 1d array.
If you want your matrix to contiguous locations, declare it as a one dimensional array and perform the row and column calculations yourself:
int contiguous_matrix[81];
int& location(int row, int column)
{
return contiguous_matrix[row * 9 + column];
}
You can also iterate over each column of a row:
typedef void (*Function_Pointer)(int&);
void Column_Iteration(Function_Pointer p_func, int row)
{
row = row * MAXIMUM_COLUMNS;
for (unsigned int column = 0; column < 9; ++column)
{
p_func(contiguous_matrix[row + column]);
}
}
For static declared arrays you can access them like continuous 1D array, p = matrix[0] will give you the 1st column of 1st row. Then the 1D array can be accessed like p[i], *(p+i), or p[current_raw * raw_size + current_column).
The things are getting tricky if a 2D array is represented with **p as it will be interpreted as an array of pointers to 1D arrays.
I don't know if this is a efficient solution but by doing this way I'm able to get the column,
int arr[9][2] = { {2, 57}, {3, 66}, {4, 73}, {5, 76}, {6, 79}, {7, 81}, {8, 90}, {9, 96}, {10, 100}};
int c[18];
int co = 0;
for (auto & i : arr) {
for (int j : i) {
c[co++] = j;
}
}
for (int i = 0; i < co; ++i) {
if (i % 2 != 0)
std::cout << c[i] << " ";
}