Pointer to array - initialize element - 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 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?

Related

Initialize vector passed by reference

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.

Assign values from vector to dynamic array (C++)

I have a vector of vertices of a line called lineVertices and I am going to pass this data to draw an OpenGL shape, so this vector must be in the form of an array, I'm assuming. I've tried the following code:
float* lineArray = new float[lineVertices.size()]();
for (unsigned i = 0; i < lineVertices.size(); i++) {
lineArray[i] = lineVertices.at(i);
}
However, it appears that the each element of the vector is getting assigned to the first element of the array only. Even though the lineArray identifier is a pointer to the first element, is there another way to access the different elements of the dynamic array?
If it helps, when I am debugging, it says that the size of lineArray is always 1, although lineVertices' size is clearly greater than 1.
I have also tried the code below, but this also does not work.
float* lineArray = &lineVertices[0];
Any help is appreciated!
You can pass a std::vector directly to OpenGL functions taking a pointer to an array. Just use the ::data() member function. Example:
std::vector<float> vec = ...;
glVertex2fv(vec.data()); // only uses the first two elements
OpenGL functions like this take a pointer to one or more elements. This doesn't have to be a raw array created with new; it just has to be a pointer to a consecutive list of elements. Use vector.data() to get a pointer to a std::vector's contents (first element).
If you really want to create a new array with manual memory management, you can do this (same effect as the code you posted):
float* arr = new float[vec.size()]; // NO () - not a constructor, but operator new[]
for (size_t i = 0; i < vec.size(); i++) {
arr[i] = vec[i];
}

Misunderstanding of C++ array structure

I'm new to C++ and I learned with different tutorials, in one of them I found an example of code:
I have pointed by numbers of lines, that I completely do not understand;
Does this array in array or something like that?
I can understand the second call, but what is the first doing? There is already
"coordinates[blocks[num]]", aren't there? Why need again blocks(i) ?
How do you make this part of the code easier? Did struct with this arrays
don't make easier getting value from arrays?
Thanks in advance!
// Global vars
Struct Rect {
float left;
}
Rectangle *coordinates;
int *blocks;
coordinates = new Rect[25];
blocks = new int[25];
// in method storing values
const int currentBlock = 0; //var in cycle
coordinates[currentBlock].left = column;
blocks[currentBlock] = currentBlock;
//get element method
const Rect& classA::Coords(int num) const
{
return coordinates[blocks[num]]; //(2)
}
//and calling this method like
Coords(blocks[i]); //(3)
Coords(i); //(3)
// (4)
No, not really. Lots of people will think of them as arrays and even describe them as arrays, but they're actually not. coordinates and blocks are both pointers. They just store a single address of a Rect and an int respectively.
However, when you do coordinates = new Rect[25];, for example, you are allocating an array of 25 Rects and setting the pointer coordinates to point at the first element in that array. So, while coordinates itself is a pointer, it's pointing at the first element in an array.
You can index coordinates and blocks like you would an array. For example, coordinates[3] will access the 4th element of the array of Rects you allocated. The reason why this behaves the same as arrays is because it actually is the same. When you have an actual array arr, for example, and you do arr[4], the array first gets converted to a pointer to its first element and then the indexing occurs.
No, this is not an array of arrays. What it is doing is looking up a value in one array (blocks[num]) and using that to index the next array (coordinates[blocks[num]]). So one array is storing indices into the other array.
I'll ignore that this won't compile, but in both cases you are passing an int to the Coords function. The first case looks incorrect, but might not be. It is taking the value at blocks[i], passing that to the function then using that value to index blocks to get another value, then using that other value to index coordinates. In the second case, you are just passing i, which is being used to index blocks to give you a value with which you index coordinates.
That's a broad question that I don't think I can answer without knowing exactly what you want to simplify and without seeing some real valid code.

Multi-Dimensional Arrays--> Null Object Pointers

I am trying to develop a C++ application. Part of the Application is meant to create and initiate some properties of an Object and then store the object in a multi-dimensional array. Problem is after Object creation and storing the objects in the array, retrieving the Object values gives me pointers to NULL.
Please see code below for exact implementation:
Cell** TestMain::convertToMatrix(){
//char[] lengthArr = arra[0];
//int[][] temp
int rowCount = getCurrentRowCount(); // Gives the row count of the multi-dimensional array
int colCount = getCurrentColCount(); // Gives the column count of the multi-dimensional array
Cell** cellList;
cellList = new Cell*[rowCount];
for (int rowIter=rowCount-1;rowIter>=0; rowIter-- ){
cellList[rowIter] = new Cell[colCount];
for (int colIter=colCount-1;colIter>=0;colIter--) {
Cell *currentCell = new Cell(arra[rowIter][colIter],rowIter,colIter);
//Calculate weights
if (0==currentCell->getValue()) currentCell->setWeight(0);
if (1== currentCell->getValue()) {
if (isEdge(rowIter,colIter)) {
currentCell->setWeight(1);
}
else {
//currentCell->setWeight(1 + getMinimumValue(cellList[rowIter+1][colIter]->getWeight(),cellList[rowIter+1][colIter+1]->getWeight(),cellList[rowIter][colIter+1]->getWeight() ) );
currentCell->setWeight(1 + getMinimumValue(cellList[rowIter+1][colIter].getWeight(),cellList[rowIter+1][colIter+1].getWeight(),cellList[rowIter][colIter+1].getWeight() ) );
}
}
cellList[rowIter][colIter] = *currentCell;
}
}
return cellList;
}
`
Here is the code that performs the checking later in the code:
void StrawberryMain::printField(Cell** arrayOfCells) {
int row=0;
int column=0;
int maxRowCount= getCurrentRowCount();
int maxColCount = getCurrentColCount();
for (;row<maxRowCount;row++) {
Cell *cellArr = arrayOfCells[row];
for (;column<maxColCount;column++) {
Cell currentArrayCell = cellArr[column];
/*if (currentArrayCell==NULL){ // This line throws an error ->No match for ‘operator==’ in ‘currentArrayCell == 0’. Why?
printf("Returned Pointer for Cell was NULL");
}
else { */
printf("%s(%s)|", currentArrayCell.getWeight(),currentArrayCell.getValue());
/
//}
printf("\n");
}
}
When I run the program I get a whole load of nulls printed on my screen as output.( One null for every object supposed stored in the array
I come from a Java background ( although I have dabbled in QT C++ before) so I am a bit miffed why this is happening. As much as I would appreciate an answer I would value an explanation as to why this happens ( or a link which explains why this happens) as I really want to understand the workings of the Language.
Thanks in anticipation.
There are several issues in your code.
As already stated in comments, you have a memory leak issue.
if (currentArrayCell==NULL){ // This line throws an error ->No match for ‘operator==’ in ‘currentArrayCell == 0’. Why?
currentArrayCell as declared in your code is a Cell object. Not a pointer to one. So you aren't comparing if a pointed to Cell is NULL. That line is trying to compare if a Cell == 0. And since you apparently haven't defined an equality operator that could work with a Cell and 0 the compiler raises that error.
With that in mind, you should note that the line Cell currentArrayCell = cellArr[column];
is actually creating a copy of a Cell. It may not be important this time. But if you write similar code where you would modify currentArrayCell, then you would find that any changes are only made to the local copy and not to the element in cellArr.
This line:
printf("%s(%s)|", currentArrayCell.getWeight(),currentArrayCell.getValue());
is most likely not doing what you wanted. s% means you must pass a string (meaning something like a const char*). However, based on your other code I'm guessing that those member functions are returning integers. printf is a low level tool and does not have the ability to convert between data types in that manner. You either need to use the appropriate format specifier for the data type (such as %d for int) or convert the values before passing them to printf.
So what happens when you use the wrong format specifier is that printf tries to byte-wise interpret whatever you actually passed as whatever type the format specifier implies. In your case, it's trying to interpret integers as character pointers. I'm actually surprised this isn't causing a crash instead of just printing nulls.
just to give you an idea
template<typename T>
struct array {
array(int m, int n) {
size_[0] = m, size_[1] = n;
data_.resize(m*n);
}
T* operator[](int i) {
return &data_.front() + i*size_[1];
}
private:
stdvector<T> data_;
size_t size_[2];
};
It seems clear from your code that you're a C guy doing C++, so here are some classes that should be aware of in light of your goals.
Boost's ublas has a matrix implementation that would be a generally superior alternative to creating your own implementation.
Baring that, at bare minimum you should probably be working with vectors instead of dynamically created arrays to reduce the potential for memory leaks.

C++ -- Pointers to Arrays -- Arrays of Pointers

I notice this has caused confusion for several people, but after reading a couple of posts on here and the cplusplus tutorial my brain is still scrambled.
Suppose I have the following variables in a header file -
int numberOfLinePoints;
D3DXVECTOR3* line; //confused as to what it is
Then in the implementation C++ file I initialize them as follows -
//both initialized in constructor
numberOfLinePoints = 25;
line = new D3DXVECTOR3[numPoints]; //array of pointers?
What does my line variable now represent?
As far as I can tell from reading links on stackoverflow it should represent an array of pointers. I then read the following however...
(1) Pointers for Beginners
...where (A) arrays of pointers, and (B) pointers to arrays, are both discussed. This left me confused once again as they both seem to work similarly.
The fact that I define my pointers in a seperate location to where I allocate (correct?) them seems to be where my confusion stems from. Am I correct that this is an array of pointers to D3DXVECTOR3 objects?
To finish - if variable line holds information about one line segment, how would I create an array of line segments? I currently have the following -
//HEADER FILE
int numberOfLineSegments;
D3DXVECTOR3** lineCollection; //array of pointers - each of which
//points to an array of pointers?
//CPP FILE
numberOfLineSegments = 8; //constructor
for(i = 0; i < numberOfLineSegments; i++) //initialization
{ //and allocation CORRECT?
lineCollection[i] = new D3DXVECTOR*[numPoints]; //of memory for Y/N
} //lineCollection
VOID createLineSegments(startPoint, endPoint) //could return array instead
{
//pseudo to generate one line segment
while != numberOfLinePoints
line[sentinel++] = interpolate(startPoint, endPoint, time_T)
//pseudo to generate array of line segments
while != numberOfLines
lineCollection[sentinel++] = line
}
Any help is much appreciated.
Your first example:
int numberOfLinePoints;
D3DXVECTOR3* line; //confused as to what it is
Declares a simple pointer to a D3DXVECTOR3. A pointer can be initialized in two ways. First:
line = new D3DXVECTOR3;
This creates a single D3DXVECTOR3 and makes line point to that object. Second:
line = new D3DXVECTOR3[numberOfLinePoints];
This creates an array of D3DXVECTOR3s and makes line point to the first element of that array. You can then use pointer arithmetics to access other elements in that array.
If you declare you pointer as double pointer:
D3DXVECTOR3** line;
You simply create another level of indirection.
int numberOfLinePoints;
D3DXVECTOR3* line; //confused as to what it is
//both initialized in constructor
numberOfLinePoints = 25;
line = new D3DXVECTOR3[numPoints]; //array of pointers?
line is an array of D3DXVECTOR3. It would be an array of pointers if D3DVECTOR3 is itself a pointer, however. Since I don't know the C++ D3D headers very well, I'm not sure.
D3DXVECTOR3** lineCollection;
Is an array of pointers, each pointer likely being a pointer to a line (that is, an array of D3DXVECTOR3).
You have two options. Memorywise, the best would be to set each entry in lineCollection to just point to the corresponding line. This is safe if you either know the lines aren't going to change (and aren't going to be freed), or if they do change you want the changes to be reflected immedaitely inside your collection.
The other option would be to create a new array for each entry in lineCollection, and copy the points from each line into this new array.
There is no correct answer, it depends on the functionality you want.
(Attempting to answer the first part of the question as succinctly as possible without introducing other issues.)
C++ (and C) uses pointers to a single item in an array as a handle for the full array. However, some pointers don't point to items in an array! You have to make the distinction between points-to-single-item and points-to-item-in-array yourself.
int length = 8;
D3DXVECTOR3* line = new D3DXVECTOR3[length];
The new[] operator returns a pointer to the first item in the array it allocates, and this assigns that value to line. Notice that because pointers don't make the distinction of single-item vs. item-in-array:
you have to store the length separately
you have to be careful you use correct indices with pointers ("line" above)
you are better off using a "real" container type, such as:
std::deque, std::vector, etc.
std::tr1::array (aka boost::array)
(The last bullet point doesn't mean you never use pointers, you just don't use them when these containers are more appropriate.)
D3DXVECTOR3 line; // Line is a D3DXVECTOR3
D3DXVECTOR3 * line; // Line is EITHER a pointer to D3DXVECTOR3 OR an
// array of D3DXVECTOR3
D3DXVECTOR3 ** line; // Line is an array of pointers to D3DXVECTOR3 OR
// an array of array of D3DXVECTOR3
This is because an array is no specific structure in memory. It is just a bunch of D3DXVECTOR3 in a row. So pointing to the first element, and you get access to all of the others.
So, having
D3DXVECTOR3** lineCollection; // An array of pointers OR an array of array!
new D3DXVECTOR[numPoints]; // A pointer to an array of D3DXVECTOR
lineCollection[i] // A pointer to an array
You initialize it by:
lineCollection[i] = new D3DXVECTOR[numPoints]; // No extra *
Yet: try to use the STL (like std::vector) instead of ugly C/Java style arrays. If you can, avoid declaring on the heap (using 'new'), but rather declaring on the stack:
D3DXVECTOR a, b, c; // a, b, and c ARE D3DXVECTOR, not pointers
std::vector<D3DXVECTOR> lines;
lines.push_back(a);
lines.push_back(b);
lines.push_back(c);
// equivalently: (you can push_back without temporaries)
std::vector<D3DXVECTOR> lines;
lines.push_back(D3DXVECTOR());
lines.push_back(D3DXVECTOR());
lines.push_back(D3DXVECTOR());
This will avoid manual memory management; it's more readable. You might not be able to always use that comfort (the way your code is organized). And if someone says something about performances, for now, don't worry. First get something working without segfaults nor memory leaks.
line = new D3DXVECTOR3[numPoints];
line holds the memory address of the first element of the array of D3DXVECTOR3.
I.e. line is a pointer to the first element of the array.
This article should clarify it.
Just look at this simple example :
case 1:
int *p = new int [N];
Here p is pointer to array of N integers and p stores starting address of the array.
case 2:
int **p = new int *[N]; //p is a pointer to pointers holding integers used for 2D array.
for(int i=0 ; i<N ; i++)
{
p[i] = new int [N]; // each element is pointer to array of integers.
}
It is applicable to all kinds of user defined types.