Initialize vector passed by reference - c++

I have a class Pixel and a class Image with a function used to update a pixel line. I want to initialize the pixel line. My problem is to initialize the vector. Actually I have this :
bool UpdateLine(std::vector<Pixel>& line, int nb)
{
bool noError = true;
line = new std::vector<Pixel>(nb);
// Do some stuff
return noError;
}
When I try this I have :
no viable overloaded '='
How can I initialize the vector ?

The expression you are using:
new std::vector<Pixel>(nb)
returns a pointer to std::vector<Pixel> (i.e.: std::vector<Pixel> *), and not a std::vector<Pixel>, which is what you need.
A distinction between initialization and assignment has to be done: you are assigning to line and not initializing it.
You can create a new vector and assign it to line by means of an assignment operator:
line = std::vector<Pixel>(nb);

What you do is assignment, not initialization.
Initializing a vector could be done like this:
std::vector<int> second (4,100); // four ints with value 100
In your case however, the vector is already declared outside of the function, so in that case you use vector::resize and do this:
line.resize(nb); // creates 'nb' objects 'Pixel'
PS: You don't need new keyword, except if you dynamically allocating memory for your vector.

Related

Does it need to initialise the variable after allocating memory?

I am trying to implement matrix multiplication in c++. I found a sample code using a class that writes in .h and .cpp files. This is just a part of the code that related to my question:
#include "Matrix.h"
// Constructor - using an initialisation list here
Matrix::Matrix(int rows, int cols, bool preallocate): rows(rows), cols(cols), size_of_values(rows * cols), preallocated(preallocate)
{
// If we want to handle memory ourselves
if (this->preallocated)
{
// Must remember to delete this in the destructor
this->values = new double[size_of_values];
}
}
void Matrix::matMatMult(Matrix& mat_left, Matrix& output)
{
// The output hasn't been preallocated, so we are going to do that
output.values = new double[this->rows * mat_left.cols];
// Set values to zero before hand
for (int i = 0; i < output.size_of_values; i++)
{
output.values[i] = 0;
}
I wonder why they initialised using the output matrix with 0s output.values[i] = 0; while it has been allocated memory before?
From cppreference on new expression:
The object created by a new-expression is initialized according to the following rules:
[...]
If type is an array type, an array of objects is initialized.
If initializer is absent, each element is default-initialized
If initializer is an empty pair of parentheses, each element is value-initialized.
"default-initialized" ints are colloquially not initialized. They have indeterminate values. The empty pair of parantheses refers to what Ted mentioned in a comment:
output.values = new double[this->rows * mat_left.cols]{};
Value initialization is described here. The case that applies here is
otherwise, the object is zero-initialized.
I wonder why they initialised using the output matrix with 0s output.values[i] = 0; while it has been allocated memory before?
Allocating memory and initializing an object are two seperate steps. Yes, the elements have to be initialzed, allocating memory is not sufficient.

Pointer to array - initialize element

I have a class Pixel and a class Image with a function used to update a pixel line. I want to initialize the pixel line. My problem is to initialize the array. Actually I have this :
bool UpdateLine(Pixel line[], int nb)
{
bool noError = true;
line = new Pixel[nb];
for (int r = 0; r < nb; r++)
{
line[r] = new Pixel(); // -> line causing troubles
// do some stuff with my pixel
[...]
}
return noError;
}
When I try this I have :
no viable overloaded '='
How can I initialize each elements for my array ?
You actually have two problems.
The first, regarding your error, is because new Pixel() results in a pointer to a Pixel object. In C++ you don't need new to create objects (do you come from a Java or C# background perhaps?). The initial allocation of the array creates the objects for you.
The second problem is that you assign to the pointer variable line, but line is a local variable inside the function. All modification to it will be lost once the function returns, and you will have a memory leak. You need to pass line by reference.
In the future when dealing with collections of a single type of data, I suggest you use std::vector instead. You still need to pass the vector by reference though, if you want to add elements to it.
line[r] = new Pixel(); // -> line causing troubles
line[r] is a Pixel object, not a pointer, so you can't assign a pointer to it.
Why aren't you using a std::vector?

array of objects where constructor has an argument

I want to have an array of objects.
Each object has a constructor with one argument.
My object array initialisation :
set s[]=new set[n]; // creates an array of n objects of class set
However, it says that I cannot do so, because my constructor requires an argument.
My Constructor:
set(int size){}
I've understood the problem, but cant think of a good solution.
What I can do, is either initialise each object seperately :
set s1(size);
set s2(size); //& so on.....
or remove the argument from constructor......both solutions are not quite satisfactory
Can anyone help me out to find a better solution to this ?
Note: 'size' value of each object is different/dynamic
#include <vector>
...
std::vector<set> s(n, set(x,y,z));
This will create a vector (a dynamically resizeable array) of n set objects, each a copy of set(x,y,z). If you want to use different constructors for various elements, or the same constructor with different arguments:
std::vector<set> s; // create empty vector
s.push_back(set(x,y,z));
s.push_back(set(y,z,x));
...
... // repeat until s.size() == n
You can make a different constructor that takes no arguments and initializes the values, and then set the values of each variable in a loop
set() {
this.size = 0;
}
and then in a for loop initialize each element with the desired size, using direct binding or a getter/setter functions.
for(int i = 0; i < n; i++) {
s[i].size = value[i]; // or create a setter function
}

C++ Regarding assigning value to Vector<Point> myVariable

C++ Regarding assigning value to Vector myVariable
Hi guys.
I have this struct
struct Point
{
int x,y;
}
and in my main.cpp i got something like this
int main()
{
vector<Point> myPoints;
myPoints[0].x = 1;
myPoints[0].y = 1;
myPoints[1].x = 2;
myPoints[1].x = 2;
return 0;
}
and i get segmentation core dump, what is wrong with setting value to the element of the vector.
Thanks for guiding!
vector<Point> myPoints;
creates an empty vector of Point objects. Since it's empty, you can't access myPoint[0], myPoint[1] etc. Attempting to do this won't auto-create elements; instead, it will invoke undefined behaviour – quite typically a segmentation fault.
Use push_back to append elements to the vector:
myPoints.push_back(Point(1,1));
or, alternatively, resize the vector so it contains default-constructed elements:
myPoints.resize(2);
You can also use an argument to the constructor of std::vector to resize it right at initialization time:
vector<Point> myPoints(2); // auto-resizes the vector to length 2
Note about push_back. In C++11, you may use emplace_back() instead of push_back() as well: myPoints.emplace_back(1,1); appends a new element to the vector by calling the Point constructor in-place, using 1,1 as the arguments to the constructor. This is the most efficient way of appending newly created elements to the vector.
You didn't initialize any objects. You need to make the objects and then put them into the vector, otherwise you are acting on something that does not exist, which is causing the segfault.
Example:
Point myPoint;
myPoints.push_back(myPoint);
myPoints[0].x = 1;
The problem is that you are trying to access elements which have not been created yet.
After this line:
vector myPoints;
you have a vector myPoints which has exactly 0 elements. Thus, myPoints[0] is meaningless.
You need to do one of the following:
Create a vector with a pre-determined size: vector<Point> myPoints(2); (note: you can expand or shrink it later), then execute myPoints[0].x=1 etc.
Use the vector's push_back method to add new elements to the vector, i.e. myPoints.push_back(Point(0, 0));
After you declare the new vector object, use the resize method to allocate space for two new elements.

Using a constructor for an array of structures

I want to create an array of structures. The structure uses a constructor as shown below:
struct struct_seedinfo {
struct_seedinfo(const mxArray *prhs[ ],const int seed_id){
mxArray *mat_coords, *mat_defvectorinit, *mat_corrcoef, *mat_roi_id;
mat_coords = mxGetField(prhs[1],seed_id,"coords");
coords = mxGetPr(mat_coords);
mat_defvectorinit = mxGetField(prhs[1],seed_id,"defvectorinit");
defvectorinit = mxGetPr(mat_defvectorinit);
mat_corrcoef = mxGetField(prhs[1],seed_id,"corrcoef");
corrcoef = *(mxGetPr(mat_corrcoef));
mat_roi_id = mxGetField(prhs[1],seed_id,"roi_id");
roi_id = *(mxGetPr(mat_roi_id));
}
double *coords;
double *defvectorinit;
double corrcoef;
double roi_id;
static int num_seeds;
};
How could I create an arbitrary sized array of this structure? I need to allocate memory for it, but it seems like I would need to allocate memory without calling the constructor, and then call the constructor later in a forloop. Is there a good or preferred way of doing this? Thanks.
You can do std::vector<struct_seedinfo>. This will create an array and it will automagically increase in size when needed.
You'll also need to overload the copy constructor and copy-assignment operator for your struct to be able to be used in a vector. You need a destructor too. This is called the Rule of Three in C++
Well since the size stay constant, you can use the following solution :
*This assumes your ok with defining a default constructor.
First declare a default constructor in your class.
struct_seedinfo(){
//If you want to initlaize something.
}
Than you can use the following to create you array :
struct_seedinfo * arr = new struct_seedinfo[size_of_array];
And then you need for each space to do your specific build :
arr[i] = struct_seedinfo(//arguments);
This is if you badly need an array, i do also think the vector solution is better.