Ivan
Ivan

Reputation: 13

How to access 2D vector by reference or pointer

I'm using Visual Studio 2017. I have two 2D vectors defined in global scope:

std::vector<std::vector<double>> my_vector1;
std::vector<std::vector<double>> my_vector2;

There are also a large number of global constants and parameters that are also defined in the global scope:

double my_parameter1 = 1;
/* lots of other constants and variables here*/

Then I have a function that needs to access one of the vectors and particular global parameters depending on the parameter passed to function:

double MakeCalculations(int vector_to_use){

  std::vector<std::vector<double>> my_vector;
  double my_parameter;     
  /*lots of other variables here */

  if(vector_to_use == 1){                         //use first vector
    my_vector = &my_vector1;                      //doesn't work
    /*assigning values for lots of parameters*/
  }
  else{                                           //use second vector
    my_vector = &my_vector2;                      //doesn't work
    /*assigning values for lots of parameters*/
  }

  /*performing calculations with my_vector here*/
}

Then:

int main(){
  my_vector1.resize(sizei1, std::vector<double>(sizej1, 0)); //initializing 2D vector
  my_vector2.resize(sizei2, std::vector<double>(sizej2, 0)); //initializing 2D vector

  /*using function MakeCalculations here alot*/
}

How can I make variable my_vector to become a reference to my_vector1 or my_vector2 depending on the passed parametervector_to_use?

Thank you

Upvotes: 1

Views: 2109

Answers (4)

sandthorn
sandthorn

Reputation: 2870

This is not intended to answer the OP question.

I'd like to add that if your 2d is fixed on at least one of dimensions. You can have contaguous 2d data like built-in array if you create it as a type of vector of array.

#include <iostream> // cout
#include <vector>   // vector
#include <array>    // array
#include <iomanip>  // fixed, setprecision

constexpr size_t col_c = 10;
size_t row = 5;

using row_t = std::array<double,col_c>;
using vec2d_t = std::vector<row_t>;
auto make_2d_of_row(size_t row) -> vec2d_t {
    return vec2d_t(row,row_t{});
}

int main()
{
  auto vec1 = make_2d_of_row(row);
  auto vec2 = make_2d_of_row(row);

  auto init = 0.0;
  for (size_t row = 0; row < vec1.size(); ++row) {
    for (size_t col = 0; col < col_c; ++col) {
      vec1[row][col] = (init += 0.1);
    }
  }

  std::cout << std::fixed << std::setprecision(1);

  for (size_t row = 0; row < vec1.size(); ++row) {
    for (size_t col = 0; col < col_c; ++col) {
      std::cout << vec1[row][col] << " ";
    }
    std::cout << "\n";
  }

}

print

0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 
2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 
3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.0 
4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 

Of course, you also can summon reference from selective pointer like in john's answer.

vec2d_t* tmp_ptr;
....
vec2d_t& my_vector = *tmp_ptr;

godbolt.org/g/ZaqmBs

wandbox.org/permlink/U3ynShvUnqkBYim2

Upvotes: 0

Athos vk
Athos vk

Reputation: 201

On this line you're trying to get the address of my_vector1 and stuff that into a variable of vector type:

my_vector = &my_vector1;

The expression '&my_myvector1' results in a value of pointer type, or more specifically, std::vector<std::vector<double>>* (note the trailing asterisk). One option is to change the type of 'my_vector1' to that of std::vector<std::vector<double>>* and change every access to its members to use the -> syntax instead of .

The other option is making my_vector a reference, but that is not possible given the current code, as you have to initialize a reference-type variable upon declaration. You can however do this by slightly refactoring the code to something like:

std::vector<std::vector<double>>& my_vector = DetermineVectorToUse(vector_to_use)

With DetermineVectorToUse being:

std::vector<std::vector<double>>& DetermineVectorToUse(int vector_to_use)
{
    if (vector_to_use == 1)
    {
        return my_vector1;
    }
    etc.
}

Note that there must be a vector for every value of vector_to_use, since you always have to (or at least, want to) return a valid reference to a vector that lives outside of the scope of the function.

Upvotes: 1

Usman Sardar
Usman Sardar

Reputation: 36

Just Change the type of your local variable "my_vector" to be a pointer.

std::vector<std::vector<double>>* my_vector;

Then you will have to access the variables with -> like so:

std::cout << my_vector->at(0).at(0) << std::endl;

Working version:

double MakeCalculations(int vector_to_use) {

std::vector<std::vector<double>>* my_vector;
double my_parameter;
/*lots of other variables here */

if (vector_to_use == 1) {                         //use first vector
    my_vector = &my_vector1;                      //doesn't work
                                                  /*assigning values for lots of parameters*/
}
else {                                           //use second vector
    my_vector = &my_vector2;                      //doesn't work
                                                  /*assigning values for lots of parameters*/
}
std::cout << my_vector->at(0).at(0) << std::endl;
my_vector->at(0).at(0) = 88;

/*performing calculations with my_vector here*/
return 0;}

Upvotes: 0

john
john

Reputation: 87959

The solution that is closest to your question while requiring minimum changes to the code you have already written is to use a temporary pointer variable.

  std::vector<std::vector<double>>* tmp_ptr;
  double my_parameter;     
  /*lots of other variables here */

  if (vector_to_use == 1) {                         //use first vector
    tmp_ptr = &my_vector1;
    /*assigning values for lots of parameters*/
  }
  else{                                           //use second vector
    tmp_ptr = &my_vector2;
    /*assigning values for lots of parameters*/
  }
  std::vector<std::vector<double>>& my_vector = *tmp_ptr;

  /*performing calculations with my_vector here*/
}

Upvotes: 4

Related Questions