I am currently struggling with Pointers in C++, especially with the input of following function:
/*
... there is an immutable array a of unsigned integers that we are not allowed to change
In order to sort this array, a second array b containing pointers to the individual
elements in a is created. We then sort the poiners in b based on the values of the pointed-to elements in a.
(d) implement the quicksort function which sorts an array of pointers as outlined above.
Note that the parameters to this function are two pointers, one to the first element in b and
one to the first element past the end of b.
*/
// Sort the range of pointers [begin; end)
void quicksort(const unsigned** begin, const unsigned** end)
{
//TODO
}
However, the Function is given const values, so is there any way to change the position of the input pointers?
A common Quicksort algorithm relies on the swap function, I tried calling
void swap (const unsigned** a, const unsigned** b){
const unsigned** temp = **a;
**a = **b;
**b = temp;
}
with
swap(begin, (end-1));
in the Quicksort Function. But that does not not work as the value for **a cannot be changed (Here, with the value **b), due to it being const.
So how would I even be able to sort the input pointers if I cannot change their order?
First of all, I know this stuff is really tricky when starting out with c/c++ and I had my fair share of confusion when I did. Therefore I will try to explain it the best way I can:
What you are trying to do in your swap function is changing the actual value of the integers behind the pointers by dereferencing two times and reassigning. You got an array of pointers which is basically a pointer to the first pointer and if you dereference that two times you end up at the actual integers, however you don't want that because this integer is constant.
Instead you want to end up at the pointers to the actual integers and swap those around. You can achieve that by dereferencing only once. If you try to reasign the pointer to change what it's pointing to, you can change the order of the array of pointers without ever touching the actual integers.
your swap function should look like this:
void swap(const unsigned int** a,const unsigned int** b) {
const unsigned int* temp = *a;
*a = *b;
*b = temp;
}
and the code where you call it could look something like this:
const unsigned int sort_without_touching[] = { 1 , 2 };
const unsigned int* ptr_array[] = {&sort_without_touching[0],
&sort_without_touching[1]};
//1 2
std::cout << *ptr_array[0] << " " << *ptr_array[1] << std::endl;
swap((ptr_array+ 0), (ptr_array+ 1));
//2 1
std::cout << *ptr_array[0] << " " << *ptr_array[1] << std::endl;
Related
As the title describes, I am trying to pass the pointer to the data of a std::vector into a function expecting a double pointer. Take as an example the code below. I have an int pointer d which is passed to myfunc1 as &d (still not sure if call it the pointer's reference or what), where the function changes its reference to the beginning of an int array filled with 1,2,3,4. However, if I have a std::vector of ints and try to pass &(vec.data()) to myfunc1 the compiler throws the error lvalue required as unary ‘&’ operand. I have already tried something like (int *)&(vec.data()) as per this answer, but it does not work.
Just for reference, I know I can do something like myfunc2 where I directly pass the vector as reference and the job is done. But I want to know if it's possible to use myfunc1 with the std::vector's pointer.
Any help will be very much appreciated.
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
void myfunc1(int** ptr)
{
int* values = new int[4];
// Fill all the with data
for(auto& i:{0,1,2,3})
{
values[i] = i+1;
}
*ptr = values;
}
void myfunc2(vector<int> &vec)
{
int* values = new int[4];
// Fill all the with data
for(auto& i:{0,1,2,3})
{
values[i] = i+1;
}
vec.assign(values,values+4);
delete values;
}
int main()
{
// Create int pointer
int* d;
// This works. Reference of d pointing to the array
myfunc1(&d);
// Print values
for(auto& i:{0,1,2,3})
{
cout << d[i] << " ";
}
cout << endl;
// Creates the vector
vector<int> vec;
// This works. Data pointer of std::vector pointing to the array
myfunc2(vec);
// Print values
for (const auto &element : vec) cout << element << " ";
cout << endl;
// This does not work
vector<int> vec2;
vec2.resize(4);
myfunc1(&(vec2.data()));
// Print values
for (const auto &element : vec2) cout << element << " ";
cout << endl;
return 0;
}
EDIT: What my actual code does is to read some binary files from disk, and load parts of the buffer into the vector. I was having troubles getting the modified vector out of a read function, and this is what I came up with that allowed me to solve it.
When you write:
myfunc1(&(vec2.data()));
You are getting the address of a rvalue. The pointed int* is so a temporary that is destroyed right after the call.
This is why you get this error.
But, as #molbdnilo said, in your myfunc1() function, you are reassigning the pointer (without caring to destroy previously allocated memory by the way).
But the std::vector already manages its data memory on its own. You cannot and you must not put your hands on it.
What my actual code does is to read some binary files from disk, and load parts of the buffer into the vector.
A solution could be to construct your std::vector by passing the iterator to the beginning and the iterator to the end of the desired part to extract in the constructor's parameters.
For example:
int * buffer = readAll("path/to/my/file"); // Let's assume the readAll() function exists for this example
// If you want to extract from element 5 to element 9 of the buffer
std::vector<int> vec(buffer+5, buffer+9);
If the std::vector already exists, you can use the assign() member function as you already did in myfunc2():
vec.assign(buffer+5, buffer+9);
Of course in both cases, you have to ensure that you are not trying to access an out of bounds element when accessing the buffer.
The problem is that you cannot take the address of data(), since it is only a temporary copy of the pointer, so writing to a pointer to it makes not that much sense. And that is good that way. You DO NOT want to pass data() to this function since it would overwrite the pointer with a new array and that would break the vector. You can remove one * from the function and only assign to it and not allocate the memory there. This will work, but make sure to allocate the memory in the caller (with resize, just reserve will result un undefined behavior, since data() is only a pointer to the beginning of the valid range [data(), data() + size()). The range [data(), data() + capacity ()) is not necessary valid.
I'm trying to implement a polynomial class consisting of an int (degree) and an integer array (the coefficients for each term). I have a function to print the polynomial, which works fine when I pass in the degree and term array directly, but things get funky when I try to put those values into an instance of my polynomial class.
I am using variadic arguments in the polynomial's constructor, such that you should be able to call polynomial(degree, ). I made sure to output each term in my va_list so I know I'm targeting what I want to.
Here's my class:
class polynomial{
public:
polynomial(int degree...){
va_list args;
_degree = degree;
int p[degree];
va_start(args,degree);
for(int i = 0; i < degree; i++){
p[i] = va_arg(args,int);
cout << p[i] << endl; //just to verify that I'm grabbing the right values.
}
va_end(args);
_terms = p;
}
int degree(){return _degree;}
int* terms(){return _terms;}
private:
int _degree;
int* _terms;
};
And here's the function(s) I'm using to print the polynomial:
void printArray(int*p, int l){
std::cout << "[";
for(int i = 0; i < l; i++){
std::cout << p[i];
if(i != l-1) std::cout << ",";
}
std::cout << "]" << std::endl;
}
void printArray(polynomial p){
printArray(p.terms(), p.degree());
}
my main function:
int main()
{
int a[3] = {2,5,3};
printArray(a,3);
polynomial p1(3,2,5,3);
printArray(p1.terms(), p1.degree());
printArray(p1);
return 0;
}
and the output:
[2,5,3]
2
5
3
[2,0,94004573]
[1,0,1]
As you can see, I call printArray() 3 times. The first time, I directly create an integer array and pass it and its length into printArray(). This time, it works fine, outputting [2,5,3] as expected. The second time, I again use the first implementation of printArray(), but this time I pass in the int* and int from an instance of my polynomial. This time, I get some array whose first two elements always seem to be 0 and 2 and whose last value is some garbage value.
The third time, I simply pass in the polynomial to the second implementation of printArray(). This seems to output [1,0,1] consistently (which is of course incorrect).
I suppose it wouldn't be too confusing if the second and third calls to printArray() generated the same garbage values, but as it stands, I am fairly lost in terms of what's happening behind the scene. Any help at all would be appreciated. Thank you!
The problem is these two lines:
int p[degree];
and
_terms = p;
The first (besides not being a non-portable variable-length array extension of your compiler) defined p to be a local variable.
The second line makes _terms point to the first element of this array.
Then the constructor ends, and the life-time of p with it, leaving you with an invalid pointer in _terms.
The natural solution is to use std::vector instead. And if you need to use pointers (because assignment/exercise requirements) you need to use dynamic allocation (using new[], and also then you need to learn about the rule of three/five).
I want to use for example this array of pointers to functions, without using STL.
That array is an array of pointers that I call functions OptionA, OptionB and so on.
int(*Functions[4])();
Functions[0] = OpionA;
Functions[1] = OptionB;
Functions[2] = OptionC;
Functions[0] = Exit;
Now if I write inside the function where I have my array
Functions[0];
I want to have called function 'OptionA' where it has been defined before for example like this:
int OptionA()
{
cout << "OPTION A";
_getch();
return 0;
}
Is it possible to do this without STL?
If not, I would like to know how to do it with STL.
You can create and pass arrays of function pointers like any other types. It's easiest if you have a type alias (my example leverages using, but typedef will also work).
#include <iostream>
using Function = int (*)(int, int);
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
void do_stuff(int a, int b, Function * fns, int cnt) {
for(auto i = 0; i < cnt; ++i) {
std::cout << "Result " << i << " = " << fns[i](a, b) << '\n';
}
}
int main() {
Function fns[2] = { add, sub };
do_stuff(10, 7, fns, 2);
return 0;
}
Output:
Result 0 = 17
Result 1 = 3
I think that what you are looking for is
How to initialize a vector of pointers
Once your vector is initialize you can send it to a function like a normal data type.
Example:
std::vector<int*> array_of_pointers{ new int(0), new int(1), new int(17) };
function(array_of_pointers);
In the declaration of the function
void function(std::vector<int*> array_of_pointers);
I hope this answer your question.
In C and C++, arrays are second-class. They cannot be passed by value by themselves, only if somehow wrapped.
As a first step, the questions you have to decide are:
Does your array have a fixed length?
And do you have to pass it by value or can you pass it by reference?
If you have to pass it by value, is that a choice you want the caller to make, or the callee to impose? In the first case, pass it by reference.
If you pass the array by reference, nothing can beat using a gsl::span, unless you pass multiple sequences all having intrinsically the same length, in which case passing pointers and a single length-argument is more efficient and maybe comfortable.
If you pass an array of variable length by value, try to use a std::vector. That's also the go-to type to pass a by-ref argument as if by-value.
Otherwise (array of fixed length, by value), nothing beats std::array.
If p is a pointer to a function, which receives no parameters, you should call it by this syntax:
p();
So, if array is an array of pointers to functions, you should call one of them using the same syntax idea:
array[0]();
Here the parentheses are important; they say "call this function, and pass no parameters to it". If you have no parentheses
array[0];
this means "select this function from the array, but do nothing with it".
It's a useless expression, like if you have an integer x, then x * 5 means "multiply x by 5 and do nothing with the result" (useless), while x *= 5 means "multiply x by 5 and replace x with the result".
I have a function where I would like to return multiple arrays. I know that in c++ does not return an array, but instead returns a pointer to an array. For example:
int* function(double array[])
But what if I need to return multiple arrays (multiple pointers to arrays? say like 2-10). I have thought of one way of doing this. One would be to just pass the arrays to a void function by reference:
void function(int a[], int b[], double c[])
But then we might be passing a lot of arrays as input. I could package all my input arrays into a class, pass the class by reference, but this seems like unnecessary structure. What is the right way to do this? Thanks
You can use std::vectors instead of arrays:
void function(vector<int> &a, vector<int> &b, vector<double> &c)
The function caller simply makes three vectors and passes them in:
vector<int> a, b;
vector<double> c;
function(a, b, c);
and the function can edit the vectors any way it likes (e.g. a.resize(10); a[0] = ...), since the vectors that the function uses are the same vectors that the caller passed in. In this way, the function can "return" multiple vectors by changing the vectors passed in by the caller.
You can use a vector of vectors
std::vector<std::vector<double>> my2Dvec;
std::vector<double> vec1, vec2, vec3;
my2dvec.push_back(vec1);
my2dvec.push_back(vec2);
my2dvec.push_back(vec3);
my2dvec[0].push_back(123.123);
my2dvec[1].push_back(456.456);
my2dvec[2].push_back(789.789);
std::cout << my2dvec[0][0] << std::endl; // 123.123
std::cout << my2dvec[1][0] << std::endl; // 456.456
std::cout << my2dvec[2][0] << std::endl; // 789.789
//----------------------------------------
NOTE: vectors become increaseingly slow the more demensions you put into them. So if you have a 3d vector of vectors be mindful of the speed hit
Try using the following:
void Function(unsigned char*&dat1, unsigned char*&dat2, unsigned char*&dat3, ...)
{
dat1 = new unsigned char[10];
dat2 = new unsigned char[20];
dat3 = new unsigned char[30];
....
}
This will pass the pointer of the array by reference.
I have been working on this and I can't seem to get this working properly. I am returning a pointer list's last value, and I would like to print it, but It is printing a very random number. I assuming that this is the memory address of the pointer, but when I dereference it, my output still does the same thing.
My Pointerlist is a list of pointers, like: list<int*> pointerList
For example, this is my method returning :
int* end() { return (pointerList.back()); }
An this is how I am calling it.
int* totry = ca.end();
cout << *totry;
This is printing the Memory Adress and not the value. Does anyone have any Ideas how to solve this?
Thanks in advance!
EDIT:
Here is what the int pointers are pointing to:
I have a list of values such as [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
And I have a list of pointers that points to different parts of that list like the following:
[0,4,8,12]
I have the Code: int* end() { return (pointerList.back()); } in my Header file, and the call in my .cpp file:
int* totry = ca.end();
cout << *totry;
This is how I declare my pointerlist
class ptrList
{
public:
std::list<value_type> listOfValues;
std::list<*int> pointerlist;
I fill my list pointers inside an "add" function, and I do it like this:
int lstsqrt = 4;
for (int a = 1; a < lstsqrt; a++)
{
int endptr = a + (int)lstsqrt;
pointerlist.push_back((&*listOfValues.begin() + endptr)); //( (lstsqrt - 1) + a) );
}
And this is my end() method
int* end() {return (pointerlist.back());}
And this is then passed to my toTry Variable.
One problem is likely to be this line:
pointerlist.push_back((&*listOfValues.begin() + endptr));
Your listOfValues is a std::list, and therefore its values are not stored in a contiguous block of memory. So you're getting an iterator to the first element with listOfValues.begin(), dereferencing the iterator with *, taking the address of that with & to get an int*, then adding some value which points somewhere off into memory that you don't know what it is.
Try doing this instead:
pointerlist.push_back((&*(listOfValues.begin() + endptr)));
where you add endptr to the iterator (to advance it along the list), then dereference and take the address. Actually you may need to use advance instead of +.