I have a recursive function that has a parameter that is a reference to a 2D matrix of object pointers. My simple question is in what format do I pass that within the function so that it would work?
I wrote this code purely for example to pass my point along and in no way represents my intended use of recursion.
This code checks for a 0 object ID value in a diagonal line through the matrix to 255,255. Then prints 0 or -1.
typedef object* m256x256[256][256];
int x = 0;
int y = 0;
int isThereZero(m256x256 & m){
if(m[x][y]->getID() == 0){ // Each object has an ID value
return 0;
}
x++;
y++;
if(x==256){
return -1;
}
return isThereZero(/*I need to pass M byref again... what do I put here?*/);
}
int main{
object* M[256][256];
/* Initialization Code */
cout << isThereZero(M);
return EXIT_SUCCESS;
}
So that by the 256th recursion m is still the same reference to M
Specific question: How do I format this to get it to compile:
int isThereZero(m256x256 & m){
return isThereZero(/*I need to pass M byref again... what do I put here?*/);
}
Rather than using global x and y, try something like so:
bool is_there_zero(const m256x256& m, int x = 0, int y = 0)
{
if (m[x][y]->getID() == 0)
return true;
if (++y == 256) {
y = 0;
if (++x == 256) {
return false;
}
}
return is_there_zero(m, x, y);
}
So we bump the y value, and if that reaches the end of the row we reset it to zero and bump the x coordinate, and finally terminate the recursion when both are equal to 256. The original matrix is untouched.
In other words, we've turned it into a poor man's double for loop, only with added function call overhead and the risk of running out of stack...
As such, I'm not at all sure why you'd want to do it this way rather than just iterating. The only advantage I can see is that, with some "creative" use of the ternary operator you could turn this into a one-line constexpr function, which could potentially be evaluated at compile-time for a fixed m, but that hardly seems worth the bother.
EDIT: Re-reading the question, I see you only wanted to test the leading diagonal, so it's a bit simpler:
bool is_there_zero(const m256x256& m, int x = 0)
{
if (x == 256)
return false;
if (m[x][x]->getID() == 0)
return true;
return is_there_zero(m, ++x);
}
Since you state, your code does not represent your actual code, it is difficult to give an educated answer (imho).
To pass by-reference as you state in your question:
int isThereZero(m256x256 & m);
If you do not change the reference you can pass by const-reference:
int isThereZero(const m256x256 & m);
This allows for some optimizations.
Of course if you pass a pointer to the array by-value:
int isThereZero(object ***m);
This will more or less work like the const-reference version, since it only passes a pointer, not the whole array.
I hope this answers your question
Ah thank you all. You all contributed a little bit to helping me find my problem. As most of you probably realized. Just calling return isThereZero(m); Should have worked. This helped me find that the error was in the syntax of other areas of my program and only caused the compiler to tell me that the problem was with the passing and calling of this array.
Related
When doing something like this:
i2 = i++;
The ++ operator will return i, and then it will increment i by one.
Can a function also return something and then execute its code?
No, once the scope of a function is over (at the closing }), no further code can be executed.
However, the function can store the old state of the input, modify the input, and return the old value of the input. This gives the effect of executing code after the function returns a value. As an example:
int f(int &n) {
int x = n; // store input
n = 42; // input is modified before return
return x; // old input is returned
}
int b = f(a); // b is equal to a
// but now a is 42
As you have observed, post-increment is an example of where such behavior is useful. Another example would be std::exchange, which gives the appearance of modifying the input after returning a value.
If you were to implement postfix increment by yourself, you would first store the original value, then use increment but still return the original value:
Number Number::operator++ (int)
{
Number ans = *this;
++(*this);
return ans;
}
You may check this FAQ for more details: https://isocpp.org/wiki/faq/operator-overloading#increment-pre-post-overloading
So there is no function code execution after return in C++.
I have a method, which i want to execute differently depending on if the passed variable is an element of a vector or not, like for example:
void method(int a){
if (/*a is an element of a vector*/) //do one thing
else //do another thing
}
and then in main:
vector<int> a;
a.pushback(1);
int b = 1;
method(a[0]); // does one thing
method(b); // does the other thing
What is the simplest way to do that?
Well, for all cases this is impossible, because it actually requires your function to look at how it is executed, and there is no such thing in C++. The hated eval() comes to mind.
But in a certain case, when your vector is a global entity, you could pass your variable by link instead of value. Then, you can check if it fits the space between the start and end of the desired vector. This is how it is done(not tested though, but should work)
vector<int> v;
//fill it somewhere somehow
void method(int& a)
{
int* beg = v.data();
int* end = beg + v.size();
int* val = &a;
if ((val >= beg) && (val < end))
{
//it is a part of vector
}
else
{
//it is not a part of vector
{
}
Problem is that you really shouldn't do it this way... As people in the comments said, it DOES look like an XY problem.
An int is an int. An int does not wear a label around its neck, telling everyone where it came from. When an int is passed to a function, there is nothing that specifies where the int originates.
You should take this as an opportunity to learn about iterators, and implement an overloaded method that takes either an
void method(int);
for a parameter, or a
void method(std::vector<int>::iterator iter);
for a parameter (or, perhaps, a const_iterator), and invoke the alternative method() by passing it an iterator to the int in your vector.
I have a multi-file program that reads data from a file and stores the values in various arrays. The size of the arrays is not known during the compiling. After the values are stored, I use another function to determine the maximum and minimum of each array and return the max/min. Before the "return maximum" statement, the values in the array are correct. After "return maximum", the values are changed or erased.
Here is some of the code including one of the 2D arrays and one of the 1D arrays (there are a few more of those but I removed them so there's less code for you to look at)
**EDITED:
FunctionValues.h: ** removed destructor block
class FunctionValues
{
//define variables, set up arrays of unknown size
public:
float **xvel;
int *imax;
int vessels;
int tot_gridpt;
public:
//Constructor -- initialization of an object performed here
FunctionValues(): xvel(NULL), imax(NULL) {}
//Destructor
~FunctionValues() {
}
void read_function(string filename);
};
FunctionValues.cpp: (this reads a file with some imax values, vessel numbers and velocities and stores them in the appropriate arrays, the other includes are also there) All the arrays made are stored in FunctionValues myval object
#include "FunctionValues.h"
using namespace std;
void FunctionValues::read_function(string filename)
{
std::ifstream myfile(filename.c_str());
//acquire variables
myfile >> vessels; //number of vessels
imax = new int[vessels];
//... code reading the file and storing them, then imax and some other values are multiplied to get int tot_gridpt
xvel = new float *[vessels];
for (int i = 0; i < vessels; i++)
{
xvel[i] = new float[tot_gridpt];
}
//arrays filled
for (int i = 0; i < limiter; i++)
{
myfile >> xvel[count][i];
}
}
Gridpts.cpp: ** range() arguments and parameters
#include "FunctionValues.h"
#include "Gridpts.h"
using namespace std;
// forward declarations
float range(float **velocities, const FunctionValues *myval, int num);
void Gridpts::create_grid(FunctionValues *myval, int ptsnum)
{
//find range, 1 for max, 0 for min from smooth wall simulation results rounded to the nearest integer
float maximum = range(myval->xvel, &myval, 1);
float minimum = range(myval->xvel, &myval, 0);
}
range.cpp: ** arguments changed to pass by pointer
float range(float **velocities, const FunctionValues *myval, int num)
{
if (num == 1)
{
float maximum = 0;
for (int round = 0; round < myval->vessels; round++)
{
for (int count = 0; count < myval->tot_gridpt; count++)
{
if (velocities[round][count] > maximum)
{
maximum = velocities[round][count];
}
}
}
maximum = ceil(maximum);
return maximum;
}
main.cpp:
corner_pts.create_grid(&myval, ptsnum);
This is where the error occurs. cout << "CHECKPOINT: " << myval.xvel[0][0] before "return maximum;" gives -0.39032 which is correct. After "return maximum", causes nothing to be printed and then the program crashes when trying run range() again using the xvel array. Similarly for myval.imax[0].
I apologize for copying in so much code. I tried to only include the essential to what is happening with the array. I have only started programming for about a month so I'm sure this is not the most efficient way to write code but I would greatly appreciate any insight as to why the arrays are being changed after returning a float. Thank you in advance for your time. (And if I have broken any rule about posting format, please let me know!)
So your program crashes when you call range() the second time. Therefore, your issue is most likely there.
Your program is crashing because you are taking your FunctionValues parameter by value, which is then destroyed at the end of the scope of the function, since it is local to the function.
// issue with myval being taken as a copy
float range(float **velocities, FunctionValues myval, int num)
{
//...
} // destructor for local function arguments are called, including myval's destructor
Explanation
Your function parameter FunctionValues myval is taken by copy. Since you have no copy constructor defined, this means that the default copy behavior is used. The default copy behavior simply copies the object data from the supplied argument at the call site.
For pointers, since they hold addresses, this means that you are copying the addresses of those pointers into an object local to the range() function.\
Since myval is local to the range() function, its destructor is called at the end of the scope of the function. You are left with dangling pointers; pointers holding the memory addresses of memory that you have already given back to the free store.
Simplified example of your error:
#include <iostream>
class X
{
public:
X() : p{ new int{ 0 } }
{
}
~X()
{
std::cout << "Deleting!" << std::endl; // A
delete p; // B
}
private:
int* p;
};
void func(X param_by_value) // C
{
// ...
}
int main()
{
X x; // D
func(x); // E
func(x); // F
}
You have variable x (D). You use it to call the function func() (E).
func() takes a parameter of type X by value, for which the variable name is param_by_value (C).
The data of x is copied onto param_by_value. Since param_by_value is local to func(), its destructor is called at the end of func().
Both x and param_by_value have an int* data member called p that holds the same address, because of 3..
When param_by_value's destructor is called, we call delete on param_by_value's p (B), but x's p still holds the address that was deleted.
You call func() again, this time the same steps are repeated. x is copied onto param_by_value. However, this time around, you try to use memory that has been given back to the free store (by calling delete on the address) and (luckily) get an error. Worse yet, when main() exits, it will attempt to call x's destructor again.
You need to do some research into function parameters in C++. Passing by value, passing by reference, passing by pointer, and all of those combined with const.
As user #MichaelBurr points out, you should also look up the rule of three (and rule of five).
I'm just wondering why you opted not to use functionality like std::max/min_element in and std::valarray/vector to allocate a contiguous chunk of memory?
Worse case scenario, if you're a fan of the explicit nature of 2d arrays x[a][b] you could create a basic matrix:
template <typename T>
class Matrix {
public:
Matrix(std::valarray<int>& dims) : dims(dims) {}
Matrix(std::valarray<int>& dims, std::valarray<T>& data) : dims(dims), data(data) {}
std::Matrix<T> Matrix::operator[](int i) {
auto newDims = std::valarray<int>(dims[1], dims.size() - 1);
auto stride = std::accumulate(std::begin(newDims), std::begin(newDims) + newDims.size(), 1, [](int a, int b){ return a * b; })
auto newData = std::valarray<T>(data[i * stride], data.size() - (i * stride));
return Matrix<T>(newDims, newData);
}
protected:
std::valarray<T> data;
std::valarray<int> dims;
}
I think more reliance on the standard libraries for their correctness will likely solve any memory access/integrity issues.
** Please don't criticize the purpose of the code itself. It's from Pat Morin's Open Data Structures book. Not my first choice, its assigned reading/practice. I just wanted to know if there is a way to differentiate, or a better way to go about this. Textbook--> http://opendatastructures.org/ods-cpp/**
** Another note: I'm coming from Java, where this would be allowed. My code still compiles, it just "fixes" it**
I'm surprised nothing like this has come up before because it seems like such a simple question. Perhaps it's buried or I'm not using the correct terminology.
I have a for loop that goes through the data in a vector. I need to return the value being searched for if it's found. What if it's not found? Here is my code.
int find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return NULL;
}
Pretty simple. Let's say 0 is one of the valid values that I might need to record and search for. As it is, it actually returns 0, not "NULL". Research says it is one and the same. How can I specify or differentiate? Other than returning an obsqure number that won't come up in the program because we may not always have that luxury (like -1 or -9999999). For example, searching for your account balance. No number is impossible.
Why would you return the value you are searching for from a find function? You already know the value, its the one you passed to the function. Return the position of the found element instead, as this information is much more useful. When the value isn't found, you can return a special position, like -1. Or you can follow the model of the standard library and return the end iterator, which signifies a position that is one past the end of the range.
You can write the function in several ways
bool find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i != bag.size();
}
Or
std::vector<int>::size_type find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i;
}
Or
#include <algorithm>
//...
std::vector<int>::iterator find( int x )
{
return std::find( beg.begin(), bag.end(), x );
}
And use the functions correspondingly the following ways
if ( find( x ) ) { /*...*/ }
if ( find( x ) != bag.size() ) { /*...*/ }
if ( find( x ) != bag.end() ) { /*...*/ }
As for your general question in the title of the post
What if I need to differentiate 0 from NULL in C++?
then you need fo use nullptr instead of NULL that to differentiate 0 from NULL.:)
#define XOR_MSB(x) (x^0x80000000)
int find(bool found) {
return found ? XOR_MSB(0) : NULL;
}
int main()
{
int value = find(false);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
value = find(true);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
return 0;
}
you're talking about an evil practice, coming from Java and C# developers where you can return null as invalid result.
well, you can't do it in C++.
Java and C# declares almost everything on the heap, and accessing objects is done done always by the reference. this means you always return a pointer from a function, and you can always return a null as a return value.
this is not so possible in C++ when a function does not return a pointer. for example , the function std::string returnString() can't return null as a return value.
more over, you should not return null as invalid output. this is wrong on so many levels even in C# and Java! if your function fails, simply throw an exception, or make your return value be passed as reference-argument and make the function return true or false.
you can also find less-agressive solutions like returning -1 (like indexOf() in javascript) or return somthing like std::string::npos or std::vector:end which are more C++ STL tuned.
This is what boost::optional<T> is for. Effectively, this type represents "There may be a T, but there may not be a T". The user may check if there is a T or not. Ideally you would not depend on any special value of T but use an optional<T> instead. optional<T> is fully generic and may apply to pretty much any T you may need to use, it does not depend on some special value or state of T.
boost::optional<int> find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return boost::none;
}
int main() {
if (auto opt = find(5))
std::cout << *opt;
}
Do not ever use NULL, it is a terrible thing. Always use nullptr which is substantially safer and one of the reasons why it is safer is because your wrong code would not compile.
I got this library of mathematical routines ( without documentation ) to work on some task at college. The problem I have with it is that all of its functions have void return type, although these functions call one another, or are part of another, and the results of their computations are needed.
This is a piece of ( simplified ) code extracted from the libraries. Don't bother about the mathematics in code, it is not significant. Just passing arguments and returning results is what puzzles me ( as described after code ) :
// first function
void vector_math // get the (output) vector we need
(
double inputV[3], // input vector
double outputV[3] // output vector
)
{
// some variable declarations and simple arithmetics
// .....
//
transposeM(matrix1, matrix2, 3, 3 ); // matrix2 is the result
matrixXvector( matrix2, inputV, outputV) // here you get the result, outputV
}
////////
// second function
void transposeM // transposes a matrix
(
std::vector< std::vector<double> > mat1, // input matrix
std::vector< std::vector<double> > &mat2, // transposed matrix
int mat1rows, int mat1columns
)
{
int row,col;
mat2.resize(mat1columns); // rows
for (std::vector< std::vector<double> >::iterator it=mat2.begin(); it !=mat2.end();++it)
it->resize(mat1rows);
for (row = 0; row < mat1rows; row++)
{
for (col = 0; col < mat1columns; col++)
mat2[col][row] = mat1[row][col];
}
}
////////
// third function
void matrixXvector // multiply matrix and vector
(
std::vector< std::vector<double> > inMatrix,
double inVect[3],
double outVect[3]
)
{
int row,col,ktr;
for (row = 0; row <= 2; row++)
{
outVect[row]= 0.0;
for (ktr = 0; ktr <= 2; ktr++)
outVect[row]= outVect[row] + inMatrix[row][ktr] * inVect[ktr];
}
}
So "vector_math" is being called by the main program. It takes inputV as input and the result should be outputV. However, outputV is one of the input arguments, and the function returns void. And similar process occurs later when calling "transposeM" and "matrixXvector".
Why is the output variable one of the input arguments ? How are the results being returned and used for further computation ? How this kind of passing and returning arguments works ?
Since I am a beginner and also have never seen this style of coding, I don't understand how passing parameters and especially giving output works in these functions. Therefore I don't know how to use them and what to expect of them ( what they will actually do ). So I would very much appreciate an explanation that will make these processes clear to me.
EXTRA :
Thank you all for great answers. It was first time I could barely decide which answer to accept, and even as I did it felt unfair to others. I would like to add an extra question though, if anyone is willing to answer ( as a comment is enough ). Does this "old" style of coding input/output arguments have its name or any other expression with which it is referred ?
This is an "old" (but still popular) style of returning certain or multiple values. It works like this:
void copy (const std::vector<double>& input, std::vector<double>& output) {
output = input;
}
int main () {
std::vector<double> old_vector {1,2,3,4,5}, new_vector;
copy (old_vector, new_vector); // new_vector now copy of old_vector
}
So basically you give the function one or multiple output parameter to write the result of its computation to.
If you pass input parameters (i.e. you don't intend to change them) by value or by const reference does not matter, although passing read only arguments by value might be costly performance-wise. In the first case, you copy the input object and use the copy in the function, in the latter you just let the function see the original and prevent it from being modified with the const. The const for the input parameters is optional, but leaving it out allows the function to change their values which might not be what you want, and inhibits passing temporaries as input.
The input parameter(s) have to be passed by non-const reference to allow the function to change it/them.
Another, even older and "C-isher" style is to passing output-pointer or raw-arrays, like the first of your functions does. This is potentially dangerous as the pointer might not point to a valid piece of memory, but still pretty wide spread. It works essentially just like the first example:
// Copies in to int pointed to by out
void copy (int in, int* out) {
*out = in;
}
// Copies int pointed to by in to int pointed to by out
void copy (const int* in, int* out) {
*out = *in;
}
// Copies length ints beginning from in to length ints beginning at out
void copy (const int* in, int* out, std::size_t length) {
// For loop for beginner, use std::copy IRL:
// std::copy(in, in + length, out);
for (std::size_t i = 0; i < length; ++i)
out[i] = in[i];
}
The arrays in your first example basically work like pointers.
Baum's answer is accurate, but perhaps not as detailed as a C/C++ beginner would like.
The actual argument values that go into a function are always passed by value (i.e. a bit pattern) and cannot be changed in a way that is readable by the caller. HOWEVER - and this is the key - those bits in the arguments may in fact be pointers (or references) that don't contain data directly, but rather contain a location in memory that contains the actual value.
Examples: in a function like this:
void foo(double x, double output) { output = x ^ 2; }
naming the output variable "output doesn't change anything - there is no way for the caller to get the result.
But like this:
void foo(double x, double& output) { output = x ^ 2; }
the "&" indicates that the output parameter is a reference to the memory location where the output should be stored. It's syntactic sugar in C++ that is equivalent to this 'C' code:
void foo(double x, double* pointer_to_output) { *pointer_to_output = x ^ 2; }
The pointer dereference is hidden by the reference syntax but the idea is the same.
Arrays perform a similar syntax trick, they are actually passed as pointers, so
void foo(double x[3], double output[3]) { ... }
and
void foo(double* x, double* output) { ... }
are essentially equivalent. Note that in either case there is no way to determine the size of the arrays. Therefore, it is generally considered good practice to pass pointers and lengths:
void foo(double* x, int xlen, double* output, int olen);
Output parameters like this are used in multiple cases. A common one is to return multiple values since the return type of a function can be only a single value. (While you can return an object that contains multiple members, but you can't return multiple separate values directly.)
Another reason why output parameters are used is speed. It's frequently faster to modify the output in place if the object in question is large and/or expensive to construct.
Another programming paradigm is to return a value that indicates the success/failure of the function and return calculated value(s) in output parameters. For example, much of the historic Windows API works this way.
An array is a low-level C++ construct. It is implicitly convertible to a pointer to the memory allocated for the array.
int a[] = {1, 2, 3, 4, 5};
int *p = a; // a can be converted to a pointer
assert(a[0] == *a);
assert(a[1] == *(a + 1));
assert(a[1] == p[1]);
// etc.
The confusing thing about arrays is that a function declaration void foo(int bar[]); is equivalent to void foo(int *bar);. So foo(a) doesn't copy the array a; instead, a is converted to a pointer and the pointer - not the memory - is then copied.
void foo(int bar[]) // could be rewritten as foo(int *bar)
{
bar[0] = 1; // could be rewritten as *(bar + 0) = 1;
}
int main()
{
int a[] = {0};
foo(a);
assert(a[0] == 1);
}
bar points to the same memory that a does so modifying the contents of array pointed to by bar is the same as modifying the contents of array a.
In C++ you can also pass objects by reference (Type &ref;). You can think of references as aliases for a given object. So if you write:
int a = 0;
int &b = a;
b = 1;
assert(a == 1);
b is effectively an alias for a - by modifying b you modify a and vice versa. Functions can also take arguments by reference:
void foo(int &bar)
{
bar = 1;
}
int main()
{
int a = 0;
foo(a);
assert(a == 1);
}
Again, bar is little more than an alias for a, so by modifying bar you will also modify a.
The library of mathematical routines you have is using these features to store results in an input variable. It does so to avoid copies and ease memory management. As mentioned by #Baum mit Augen, the method can also be used as a way to return multiple values.
Consider this code:
vector<int> foo(const vector<int> &bar)
{
vector<int> result;
// calculate the result
return result;
}
While returning result, foo will make a copy of the vector, and depending on number (and size) of elements stored the copy can be very expensive.
Note:
Most compilers will elide the copy in the code above using Named Return Value Optimization (NRVO). In general case, though, you have no guarantee of it happening.
Another way to avoid expensive copies is to create the result object on heap, and return a pointer to the allocated memory:
vector<int> *foo(const vector<int> &bar)
{
vector<int> *result = new vector<int>;
// calculate the result
return result;
}
The caller needs to manage the lifetime of the returned object, calling delete when it's no longer needed. Faililng to do so can result in a memory leak (the memory stays allocated, but effectively unusable, by the application).
Note:
There are various solutions to help with returning (expensive to copy) objects. C++03 has std::auto_ptr wrapper to help with lifetime management of objects created on heap. C++11 adds move semantics to the language, which allow to efficiently return objects by value instead of using pointers.