For example, I want to declare pointer to array and to don't wanna initialize it. Then, I want pass it to a function and initialize it exactly in function. How can I do it in C++?
void F(int *B, const int& N) {
B = new int[N];
for (int i = 0; i < N; ++i) B[i] = i;
}
int main() {
int N = 4;
int *B = nullptr; // doesn't work
F(*B, N);
for (int i = 0; i < N; ++i)
cout << B[i] << endl;
return 0;
}
It evokes/produces error corresponds to the problem that B has no reference to point and, therefore he can't initialize array.
error: Process finished with exit code 11
The pointer you pass is a copy of the original pointer. When you modify B in F, B i main() remains the same.
You need to pass the pointer by reference or pass a pointer to the pointer:
void F(int*& B, const int& N) {
B = new int[N];
for (int i = 0; i < N; ++i) B[i] = i;
}
int main() {
int N = 4;
int *B = nullptr; // doesn't work
F(B, N); //no operator here, just pass the pointer by reference
for (int i = 0; i < N; ++i)
cout << B[i] << endl;
return 0;
}
or
void F(int** B, const int& N) {
*B = new int[N];
for (int i = 0; i < N; ++i) (*B)[i] = i;
}
int main() {
int N = 4;
int *B = nullptr; // doesn't work
F(&B, N); //need address-of operator
for (int i = 0; i < N; ++i)
cout << B[i] << endl;
return 0;
}
Also, since you decided to use manual memory management, you are also responsible to release the memory acquired with new. This is not necessary if you use std::vector as your container instead of raw pointer (or std::unique_ptr or other containers).
for (int i = 0; i < N; ++i)
cout << B[i] << endl;
delete[] B; //release memory after use
return 0;
You have at least two problems.
The first in in the call where you use *B. *B is the same as B[0], which means you're attempting to pass a single int element to the function. But since B is a null pointer, the dereference will lead to undefined behavior.
Correct (to fit the shown function signature) would be plain B:
F(B, N);
The second problem is that passing arguments to functions by default is done by value. Which means that the value of B is copied into the local variable B inside the function F.
When you assign to B in the function you only change the local copy, and the original value in the main function will be unmodified.
To solve this you need to pass B by reference:
void F(int*& B, const int N) { ... }
Related
need a better approach to pass address arr[0][2], given that is has to be received in a double pointer.
want to pass arr[0][2] without storing in any other variable.
#include <iostream>
using namespace std;
int help(int **arr)
{
cout<<**arr;
}
int main()
{
{
int n=3,m=3,k=0;
int **arr = new int*[n];
for(int i = 0; i < n; i++) {
arr[i] = new int[m];
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
arr[i][j]=k;
k++;
}
}
int *g=*arr+2;
int **h=&g;
help(h);
}
}
There is no better way. Unfortunately C++ syntax x[y] can be used to mean two very different operations: if x is an array then is indexing, if x is a pointer they it's indirection and indexing.
If a caller expects a pointer to a pointer and you've a bidimensional matrix there's nothing you can do except actually creating the pointer that is not present in the matrix and pass its address.
The fact that with an array of pointers, with a pointer to a pointer and with a 2d array the syntax to reach an element is x[y][z] is irrelevant... they are three very different operations.
Why not just write
int *p = &arr[0][2];
help( &p );
If you want to get an access to the whole array using a pointer of the type int ** then you can use the following approach.
#include <iostream>
void help(int **arr, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
std::cout << ( *arr )[i] << ' ';
}
std::cout << '\n';
}
int main()
{
int arr[2][3]={{1,2,3},{4,5,6}};
int *p = reinterpret_cast<int *>( arr );
help( &p, 6 );
return 0;
}
The program output is
1 2 3 4 5 6
When is it better to have a function return a pointer to an array, like this:
int * foo(int n) {
int * output = new int[n];
for (int i = 0; i < n; i++) {
output[i] = i;
}
return output;
}
int main() {
int * arr = foo(10);
return 0;
}
vs having the function not return anything but just set values of an array given in the parameters, like this:
void foo(int n, int output[]) {
for (int i = 0; i < n; i++) {
output[i] = i;
}
}
int main() {
int arr[10];
foo(10, arr);
return 0;
}
For example, I have a function that generates prime numbers, and I would like to return them as an array. Should I use the first option and return a pointer to the array, or pass an array into the function and put the values in that?
When sould I return a pointer to an array
When you have a function that creates an array - but there are better ways to do it in C++ than to return a raw pointer to the memory (since those pointers are easy to forget about so you get memory leaks etc). You can for example use the dynamic array-like std::vector:
std::vector<int> foo(size_t n) {
std::vector<int> output(n);
for(size_t i = 0; i < n; ++i)
output[i] = i;
return output;
}
std::vector<int> arr = foo(10);
std::cout << arr.size() << "\n";
std::cout << arr[9] << "\n";
vs setting values in an existing array
When you already have an array that you want to use as input and you want to modify it.
void foo(std::vector<int>& inout) {
for(int& val : inout)
val += 10; // add 10 to every element
}
Assume I have a class A that has say 3 methods. So the first methods assigns some values to the first array and the rest of the methods in order modify what is computed by the previous method. Since I wanted to avoid designing the methods that return an array (pointer to local variable) I picked 3 data member and store the intermediate result in each of them. Please note that this simple code is used for illustration.
class A
{
public: // for now how the class members should be accessed isn't important
int * a, *b, *c;
A(int size)
{
a = new int [size];
b = new int [size];
c = new int [size];
}
void func_a()
{
int j = 1;
for int(i = 0; i < size; i++)
a[i] = j++; // assign different values
}
void func_b()
{
int k = 6;
for (int i = 0; i < size; i++)
b[i] = a[i] * (k++);
}
void func_c()
{
int p = 6;
for int (i = 0; i < size; i++)
c[i] = b[i] * (p++);
}
};
Clearly, if I have more methods I have to have more data members.
** I'd like to know how I can re-design the class (having methods that return some values and) at the same time, the class does not have the any of two issues (returning pointers and have many data member to store the intermediate values)
There are two possibilities. If you want each function to return a new array of values, you can write the following:
std::vector<int> func_a(std::vector<int> vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
return vec;
}
std::vector<int> func_b(std::vector<int> vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
return vec;
}
std::vector<int> func_c(std::vector<int> vec){
//same as func_b
}
int main() {
std::vector<int> vec(10);
auto a=func_a(vec);
auto b=func_b(a);
auto c=func_c(b);
//or in one line
auto r = func_c(func_b(func_a(std::vector<int>(10))));
}
Or you can apply each function to the same vector:
void apply_func_a(std::vector<int>& vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
}
void apply_func_b(std::vector<int>& vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
}
void apply_func_c(std::vector<int>& vec){
// same as apply_func_b
}
int main() {
std::vector<int> vec(10);
apply_func_a(vec);
apply_func_b(vec);
apply_func_c(vec);
}
I'm not a big fan of the third version (passing the input parameter as the output):
std::vector<int>& func_a(std::vector<int>& vec)
Most importantly, try to avoid C-style arrays and use std::vector or std::array, and don't use new, but std::make_unique and std::make_shared
I'm assuming you want to be able to modify a single array with no class-level attributes and without returning any pointers. Your above code can be modified to be a single function, but I've kept it as 3 to more closely match your code.
void func_a(int[] arr, int size){
for(int i = 0; i < size; i++)
arr[i] = i+1;
}
void func_b(int[] arr, int size){
int k = 6;
for(int i = 0; i < size; i++)
arr[i] *= (k+i);
}
//this function is exactly like func_b so it is really unnecessary
void func_c(int[] arr, int size){
int p = 6;
for(int i = 0; i < size; i++)
arr[i] *= (p+i);
}
But if you just want a single function:
void func(int[] arr, int size){
int j = 6;
for(int i = 0; i < size; i++)
arr[i] = (i+1) * (j+i) * (j+i);
}
This solution in other answers is better, if you are going to allocate memory then do it like this (and test it!) also if you are not using the default constructor and copy constructor then hide them, this will prevent calling them by accident
class A{
private:
A(const &A){}
A() {}//either define these or hide them as private
public:
int * a, *b, *c;
int size;
A(int sz) {
size = sz;
a = new int[size];
b = new int[size];
c = new int[size];
}
~A()
{
delete[]a;
delete[]b;
delete[]c;
}
//...
};
I'm trying to declare a pointer and pass that pointer to a function where memory is allocated. Here is a minimal example:
#include <string>
#include <iostream>
using namespace std;
void alloc_mem(int &size, double *x);
int main()
{
double *X;
int imax;
alloc_mem(imax, X);
cout << "imax = " << imax << endl;
for (int i = 0; i < imax; i++) {
cout << "X = " << X[i] << endl;
}
delete[]X;
return 0;
}
void alloc_mem(int &size, double *x)
{
size = 10;
x = new double[size];
for (int i = 0; i < size; i++) {
x[i] = (double)i;
}
}
This code compiles, but I get a segmentation fault when I try to print out the values of X. I know that I'm not passing the variable into the function correctly, but I'm not sure how to do it. I believe that I'm operating on a copy of x.
Also, this code was written to reproduce an issue I'm having in a much larger code.
Parameter double *xis a local variable of function alloc_mem. When the function will end its execution the variable will be destroyed. The original variable X in main knows nothing what was done with this parameter because it was passed by value that is a copy of it was used in the function.
Either pass the pointer by pointer or by reference. For example
void alloc_mem(int &size, double **x);
void alloc_mem(int &size, double * &x);
void alloc_mem(int &size, double **x)
{
size = 10;
*x = new double [size];
for ( int i = 0; i < size; i++ ) ( *x )[i] = i;
}
void alloc_mem(int &size, double * &x)
{
size = 10;
x = new double [size];
for ( int i = 0; i < size; i++ ) x[i] = i;
}
As for me I would define the function the following way
double * alloc_mem( int &size )
{
size = 10;
x = new double [size];
for ( int i = 0; i < size; i++ ) x[i] = i;
return x;
}
if size is known before calling the function then it could be written even simpler
double * alloc_mem( int size )
{
x = new double [size];
for ( int i = 0; i < size; i++ ) x[i] = i;
return x;
}
Take into account that loop
for ( int i = 0; i < size; i++ ) x[i] = i;
can be substituted for standard algorithm std::iota For example
std::iota( x, x + size, 0.0 );
The standard C++ mechanism for defining an allocation function is operator new.
That's why the standard calls it an allocation function.
Note that operator new is different from a new-expression.
A new-expression uses the relevant allocation function (operator new function) to allocate memory, and the relevant constructor to then initialize.
However, in your case you're using (your named) allocation function just to allocate and initialize a dynamic array. Allocation and initialization are well separated responsibilities in the standard C++ language design, for very good reasons, and it would be a good idea to follow that convention. Use std::vector for your array, and if you really really really need custom allocation (very doubtful that you do), then use a custom allocator for that std::vector.
Concrete example.
Replace your current code
int main () {
// Declaring variables
double* X;
int imax;
// Calling function
alloc_mem(imax,X);
// Printing
cout << "imax = " << imax << endl;
for (int i=0; i<imax; i++) {
cout << "X = " << X[i] << endl;
}
with
#include <vector>
int main() {
int const imax = whatever();
std::vector<double> X( imax );
cout << "imax = " << imax << endl;
for (int i=0; i<imax; i++) {
X[i] = i; // If you really want these values in the vector.
cout << "X = " << X[i] << endl;
}
}
When you have an output parameter, you can pass it by reference, or by pointer.
For your size parameter, you passed by reference (since it's an out parameter).
The other parameter is a double*, so either add a reference:
void alloc_mem(int & size, double* & x) // (1)
or add another pointer (i.e. another level of indirection):
void alloc_mem(int & size, double** x) // (2)
For coherence, since you used the reference (&) technique for size, I'd suggest to use it for x as well (as in (1)).
Note also that in C++ you may want to just pass a std::vector, which knows its own size, and does automatic cleanup (thanks to its destructor):
void alloc_mem(std::vector<double> & x)
Note also that you may want to return the vector as a return value as well (simplifying your code):
std::vector<double> alloc_mem()
Code snippets:
// Note: the caller must free the memory using delete[].
void alloc_mem(int& size, double*& x) {
size = 10;
x = new double[size];
for (int i = 0; i < size; i++) {
x[i] = i;
}
}
// Note: automatic vector cleanup. No need of manual delete.
std::vector<double> alloc_mem() {
const int size = 10;
std::vector<double> x(size); // size is 0
for (int i = 0; i < size; i++) {
x[i] = i;
}
return x;
}
When I run this code I get a bad_alloc error, Am I accessing the subscript operator wrong or something ? To me it makes sense that I go to the appropriate object, it gets returned and then the subscript operator should kick in ? By the way I want to use arrays and not vectors :)
class A{
public:
A(int size)
{
array = new int[size];
}
int& operator[](const int &i)
{
return array[i]
}
private:
int * array;
};
int main() {
A ** a = new A*[10];
for(int i = 0; i < 10; i++) {
a[i] = new A(10);
for(int l = 0; l < 10; l++) {
cout << a[i][l] << endl;
}
}
}
Thanks in advance
You need to dereference the pointer before you can call operator[]
cout << (*(a[i]))[l] << endl;
Here's what needs to happen, step by step:
A* pA = a[i];
A& rA = *pA;
int& val = rA[l];
cout << val;
Currently this happens:
A* pA = a[i];
A& ra = *(pA + l); // pA is indexed as an array of As - this is wrong
cout << ra; // invalid memory