Pointers and pass by reference c++ - c++

In my main, I call the function compute_entropy and I give it a vector like this:
float entropy = h.compute_entropy(input_pic[0], & Symbol_table);
In Implementing the function itself (in h.cpp), I should not change the parameter it takes which is vector* prob.. how can I access the data of prob?
float compute_entropy(vector<Symbol>* prob)
{
float ent = 0;
vector<Symbol>* prob;
for (int i = 0; i < prob.size(); i++) //GIVES ERROR
{
ent += (prob.at(i).freq) * log2( 1 / (prob.at(i).freq) );
}
}

Because type of prob is Vector<Symbol> *, you actually need to dereference it first before accessing member. It looks like (*prob).at(i).freq.
*(A).B can also be written as A->B, so instead of (*prob).at(i).freq, you can write prob->at(i).freq. (With similar argument prob.size() becomes prob->size())
Doing it in cleaner wayBecause you never change the contents of your vector you can make the argument constant.
float compute_entropy(const vector<Symbol>* prob)
Now as we know pointers are evil, let's replace pointer with a reference.
float compute_entropy(const vector<Symbol> &prob)
{
float ent = 0;
for (int i = 0; i < prob.size(); i++) //GIVES ERROR
{
ent += (prob.at(i).freq) * log2( 1 / (prob.at(i).freq) );
}
}
While calling this, if you were calling with vector, drop the & from the argument, and if you were calling with a vector pointer, dereference it with a *.

vector<Symbol>* prob;
for (int i = 0; i < prob.size(); i++) //GIVES ERROR
.....
Because prob is a pointer, you need to use the -> operator
for (int i = 0; i < prob->size(); i++)

Related

The array in my singleton isn't keeping information after leaving a function and then it crashes when it tries to access the information again

I have an array called int **grid that is set up in Amazon::initGrid() and is made to be a [16][16] grid with new. I set every array value to 0 and then set [2][2] to 32. Now when I leave initGrid() and come back in getGrid() it has lost its value and is now 0x0000.
I don't know what to try, the solution seems to be really simple, but I'm just not getting it. Somehow the data isn't being kept in g_amazon but I could post the code.
// Returns a pointer to grid
int** Amazon::getGridVal()
{
char buf[100];
sprintf_s(buf, "Hello %d\n", grid[2][2]);
return grid;
}
int Amazon::initGrid()
{
int** grid = 0;
grid = new int* [16];
for (int i = 0; i < 16; i++)
{
grid[i] = new int[16];
for (int j = 0; j < 16; j++)
{
grid[i][j] = 0;
}
}
grid[2][2] = 32;
return 0;
}
int **grid;
g_amazon = Amazon::getInstance();
g_amazon->initGrid();
grid = g_amazon->getGridVal();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
int index;
index = (width * 4 * i) + (4 * j);
int gridval;
gridval = grid[i][j];
lpBits[index] = gridval;
lpBits[index + 1] = gridval;
lpBits[index + 2] = gridval;
}
}
It crashes when I run it at the line where sprintf_s prints out [2][2] and it also crashes when I get to gridval = grid[i][j] because it's at memory location 0x000000.
The variable
int** grid
in the initGrid() function is a local variable. Edit** When the function returns the variable is popped off the stack. However, since it was declared with the new operator the memory still exists on the heap; it is simply just not pointed to by your global grid variable.
#Dean said in comment:
I have grid as an int** grid; in class Amazon {}; so shouldn't it stay in memory or do I need a static var.
That is the problem:
local int **grid; on Amazon::initGrid::
is masking
member int **grid; on Amazon::
as the first context has higher priority in name lookup.
So initGrid() allocates memory referenced only by a local pointer. That pointer no longer exists when you return from this function, Amazon::grid was never touched on initialization and you're also left with some bad memory issues.
So, as commented by #Remy-Lebeau, I also suggest
Consider using std::vector> or std::array, 16> instead. There is no good reason to use new[] manually in this situation.

How to correctly pass an 2D array pointer as argument?

For the heads up: I am incredibly new with cpp. Being used to PHP and JS as work languages, I find pointers incredibly confusing.
So I have this Class called Macierz. The class is supposed to hold Matrixes of float variables and ought to have a constructor accepting an 2d array in order to print them into the field.
The field is declared like this
float mx3[3][3];
And the constructor has such declaration: Macierz(float**);
With the body using an additional function:
Macierz::Macierz(float** f) {
length = 3;
populateWith(f, length);
}
void Macierz::populateWith(float** val, int length) {
for (int i = 0; i < length; i++)
for (int j = 0; j < length; j++)
mx3[i][j] = val[i][j];
}
In my main() function I want to declare the class with a created float array.
I try to do it as so, but It just won't work the way God intended:
float y[3][3] = { {1.00f, 2.00f, 3.00f}, { 4.00f, 5.00f, 6.00f }, { 7.00f, 8.00f, 9.00f } };
Macierz m5(y);
This is the base template of what I want to do. I've tried making the y variable a double pointer, a regular pointer, passing via reference and it just won't kick.
What would be the most prober way to pass this variable?
Any help will be amazing, I am really a noob in this language.
You need to remember that arrays naturally decays to pointers to their first element. But that isn't recursive.
For y in your example, the decay is to a pointer to the first element of y, which is equal to &y[0]. That is a pointer to an array, and will have the type float(*)[3], which is the type you need for your arguments:
Macierz::Macierz(float (*f)[3]) { ... }
Managed to fix this by copying the float into a pointer-to-pointer types
float y[3][3] = { {1.00f, 2.00f, 3.00f}, { 4.00f, 5.00f, 6.00f }, { 7.00f, 8.00f, 9.00f } };
float** x = 0;
x = new float*[3];
for (int i = 0; i < 3; i++) {
x[i] = new float[3];
for (int j = 0; j < 3; j++) {
x[i][j] = y[i][j];
}
}
Macierz m5(x);

How to modify and pass array pointer as argument to a function which require array as argument?

This probably is a beginner question. Say for example, in the following method we use the arrays alpha and theta, which are passed as argument to the function gsl_ran_dirichlet, and the function computes new theta values and updates the same array theta.
Now, the problem is that I will not be able to initialize theta in a class as provided in the following code piece. Rather I will have to use pointers to arrays theta and alpha. How will I pass these array pointers as argument to the method gsl_ran_dirichlet?
I know it is not possible to pass pointer as argument to method which require array as argument. But what is the best way to accomplish this (assume we cannot modify gsl_ran_dirichlet)?
void test (){
double alpha[2] = { 1, 1};
double theta[2] = { 1, 1};
const gsl_rng_type * T;
gsl_rng * r;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_ran_dirichlet(r, 2, alpha, theta);
cout << theta[0] << "," << theta[1] << endl;
gsl_rng_free(r);
}
Result:
0.4,0.6
Now, I am also adding the function and the error I get in the following code, where the arrays are loaded dynamically:
void test() {
double *alpha, *theta;
alpha = new double[3];
theta = new double[3];
for(int i=0; i<3; ++i){
alpha = 1;
theta = 1;
}
const gsl_rng_type * T;
gsl_rng * r;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_ran_dirichlet(r, 3, alpha, theta);
cout << theta[0] << "," << theta[1] << "," << theta[2] << ":";
gsl_rng_free(r);
}
Error:
../test.cpp:56:11: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
../test.cpp:57:11: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
make: *** [test.o] Error 1
General:
Variable to pointer: &variable.
Pointer to variable: *pointer.
Specific:
The name of an array and a pointer to an array can be used in the same way, i.e. theta[0] and pointer_to_theta[0] are equivalent.
int foo[2] = { 1, 2 };
int * pointer_to_foo = foo;
assert( foo[1] == pointer_to_foo[1] );
Your problem is not about calling a function.
it is simply that your
for(int i=0; i<3; ++i){
alpha = 1;
theta = 1;
}
is wrong.
alpha is a double* which you cannot assign a int (1) to it.
What you are trying to do is
alpha[i] = 1;
or
*(alpha + i) = 1
And! please learn the read the error message. There is a line number in the error message and it is pointing you to where the problem is happening. You should be able to find it by yourself if you look into your line 56 and 57
Try changing the assignments in your for loop into
alpha[i] = 1;
theta[i] = 1;
double* alpha;
double* tetha;
void foo()
{
double (&refToAlpha)[2] = reinterpret_cast<double(&)[2]> (alpha);
double (&refToTetha)[2] = reinterpret_cast<double(&)[2]> (tetha);
...
gsl_ran_dirichlet(r, 2, refToAlpha, refToTetha);
}
The compilation error is simple: you assign an int to a pointer-to-a-double.
for( int i=0; i < 3; ++i ) {
alpha[i] = i; // dereference before assignment
}
The 'how-to-pass-an-array' to a function is somewhat more complicated. It's common for legacy and C-compatible code to pass in the pointer to the array, together with it's size (foo( int* values, size_t size)).
If you have the freedom of choice, you would prefer the use of standard collections (i.e. a std::vector<double>) (and algorithms like iota):
std::vector<double> alpha, theta;
std::iota(begin(alpha), end(alpha));
std::iota(begin(theta), end(theta));
and pass the collections by const reference if you want the function to read them, by value if you want the function to own a copy, by reference if you want the function to change the argument (i.e. an output argument).
void gsl_ran_dirichlet(
std::vector<double> &r, // though I prefer output args to come last
int i,
const std::vector<double> &alpha,
const std::vector<double> &theta);
The Problem in your code has nothing to do with passing an Array to a function.
In your For-loop you try ]to set a Pointer (double*) to an Integer (1) which is the cause of you compiling error.
You have to Address the position of your Array with [] to set the value.
for(int i=0; i<3; ++i){
alpha[i] = 1.0;
theta[i] = 1.0;
}
This is identical with normal Pointers. To set the Value of the Pointer you have to dereference the Adress.
int* x = new int();
*x = 5;

C++ pointer to int in loops?

Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &

Aliasing vector correctly

I have not been able to find the answer elsewhere, so I guess I just have to ask this one: I am trying to get an alias for a vector (in which int pointers are stored), as below:
void conversion(Engine * ENGINES)
{//The Engine class has a vector of int* as a public data member called SITE
for (int i = 0; i < 3; i++)
{
vector <int*>* current = &(ENGINES[i].SITE);//the problematic line
int j_max = current -> size();
cout << j_max << endl;
for (int j = 0; j < j_max; j++)
{
for (int k = 0; k < 3; k++)
{
if (*current[j][k] == 2)
*current[j][k] = 1;
if (*current[j][k] == -1)
*current[j][k] = 0;
}
}
}
}
The problem is that there seems to be an inversion of the indices for the *current[a][b]. I want to be able to use current as a normal vector, but now the indexing is reversed compared to:
vector <int*> current1 = ENGINES[1].SITE;
so that *current[i][j] = current1[j][i] for some reason. Is there a mistake in my syntax?
I believe your problem is that [] has higher precedence than unary *. So you're getting *(current[j][k]) instead of (*current)[j][k], which is what you want.
However you could eliminate that problem by just taking a reference rather than a pointer:
vector <int*>& current = (ENGINES[i].SITE); and then just remove your extra loading * operators on access to current.
The problem is that [] has greater precedence than * (dereference), so *current[i][j] is interpreted as *(current[i][j]), which is probably not what you want.
Actually, this idiom of aliasing is commonly expressed as a reference, not a pointer:
vector <int*>& current = ENGINES[i].SITE;
and use simply current[i][j].
As I suspected in my comment, use a reference.
vector <int*> &current = ENGINES[i].SITE;