2

I have an small and quite simple issue in C++. I want to fill array of struct containing double arrays. How can I do that?

typedef struct 
{
    double *inputs[2];
    double *target[1];
} Data;

Data data[] 
{
    new double[2]{10, 20}, new double[1]{30},
    new double[2]{40, 50}, new double[1]{60},
    new double[2]{70, 80}, new double[1]{90},
    new double[2]{100, 110}, new double[1]{120} 
};

and in the main()

printf("data[0]: inputs: %f %f, targets: %f\n",
                   *data[0].inputs[0],
                   *data[0].inputs[1],
                   *data[0].target[0]);

This is my idea, but when I run that it will print this:

data[0]: inputs: 10.000000 30.000000, targets: 40.000000

Of course, at the end of the array data (like 3rd or 4th item) it will cause UNAUTHORIZED ACCESS TO MEMORY

Thank you for your ideas and patience ;)

3
  • There's a lot going on in this code. Why do you new everything? Why do you use an array of size 1? Why do you use printf in c++? Why do you typedef your struct? It seems you may be mixing c and c++ tutorials. Avoid c tutorial when learning c++. Commented Jun 13, 2018 at 17:27
  • 2
    Stop using so many pointers and new right now. Use std::vector. C++ isn't C. Commented Jun 13, 2018 at 17:28
  • This is pretty much what you wrote, formatted to make it easier to see how data is initialized. You have three news per Data. Commented Jun 13, 2018 at 17:31

3 Answers 3

3

Using modern c++ makes your code both simpler and safer:

#include <iostream>
#include <array>
#include <vector>

struct Data {
    std::array<double,2> inputs;
    std::array<double,1> target;
};

int main()
{
    std::vector<Data> data = {
        { {10, 20}, {30} },
        { {40, 50}, {60} },
        { {70, 80}, {90} },
        { {100, 110}, {120} }
    };
    std::cout << "data[0]: inputs: " << data[0].inputs[0] << " " << data[0].inputs[1] << ", targets: " << data[0].target[0] << "\n";
}

Your original problem is that double *inputs[2] declares a 2 element array of pointers to double not a pointer to a 2 element array of doubles.

Sign up to request clarification or add additional context in comments.

Comments

1

Your Data struct contains 2 fields, array of 2 double pointers, and array of 1 double pointers.

That means that initalizing it takes up to 3 double pointers, which means that in your initalization really looks like this

Data data[]{
{new double[2]{ 10, 20 },   new double[1]{ 30 },        new double[2]{ 40, 50 }}, //1st object
{new double[1]{ 60 },       new double[2]{ 70, 80 },    new double[1]{ 90 }}, //2nd object
{new double[2]{ 100, 110 }, new double[1]{ 120 }} //3rd object but 2 parameters??
};

When trying to print it in a loop, 3rd object will cause a segfault, as target field hasn't been properly initalized (when debugging with Visual Studio it's set to null, not sure about other compilers).

1 Comment

Fields that are not listed by an aggregate-initialization are value-initialized, which for pointer does indeed mean that they're set to nullptr.
1

Your problem is here:

typedef struct {
    double *inputs[2];  // this
    double *target[1];  // this
} Data;

This is an array of pointers and hopefully assumed to behave live a dynamic 1D array. Simple fix is:

struct Data {
    double *inputs = nullptr;
    double *target = nullptr;
} ;

However, you have a lot of heap memory allocation using new, which makes a tedious task to delete and thereby the management of your data structure really difficult. I would strongly suggest you to use std::vector<>, which makes your task much easier and more cleaner.

#include <vector>
#include <iostream>

struct Data
{
   std::vector<double> inputs; // use  instead of double *inputs[2];
   std::vector<double> target; // use  instead of double *target[1];
   //Data(const std::vector<double>& a, const std::vector<double>& b) :inputs(a), target(b){}
};

int main()
{
   std::vector<Data> data = // now in your main structure array
   {  { {10, 20}, {30} },
      { {40, 50}, {60} },
      { {70, 80}, {90} },
      { {100, 110},{120} }
   };
   // access using range based loop now
   for(const Data& each_strcut: data)
      std::cout << each_strcut.inputs[0] << " " << each_strcut.inputs[1]
                <<"\t" << each_strcut.target[0] << std::endl;
   return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.