I am having a problem in my code right now. I can't seem to get what I need and return the address of my structure "b" so other functions can use it. If you can help me out that would be great!
Here is my necessary code:
int notFound = 0;
int choiceNumber;
int arraySize;
Basketball * b;
b = readFile(arraySize, notFound, &b);
Here is the function that I am having the problems:
Basketball * readFile(int & arraySize, int & notFound, Basketball * &b)
{
ifstream inputFile;
inputFile.open("games.txt");
if(inputFile.fail())
{
cout << "The file name \"games.txt\" was not found!" << endl;
notFound = 1;
}
else
{
inputFile >> arraySize;
b = new Basketball [arraySize];
for (int i = 0; i < arraySize; i++)
{
inputFile >> b[i].visitTeam >> b[i].homeScore >> b[i].visitScore;
}
return & b;
}
}
My build errors are these:
Error: invalid intialization of non-const reference of type basketball*& from an rvalue of type Basketball**
Error: In passing arguement 3 of Basketball* readfile(int&,int&, Basketball*&)
Error: Cannot convert Basketball** to Basketball* in return
If you can point me in the right direction that would be great!
The variable b already is a pointer, using &b will create a pointer to the pointer. Drop the address-of operator &.
The error message is very clear about it, same with you returning a pointer to a pointer when you declared is a returning only a single pointer.
"return b;" is what yoy want, not "return &b"
&b Is the address of Basketball*, so you would end with incorrect Basketbal**
As others already wrote, since b is already a pointer, return b; will fix your error.
If you do return &b; you are returning the address of a pointer, i.e. a "double level indirection" pointer, which would be a Basketball**.
However, let me add that you may simplify your C++ code using more modern idioms, like using std::vector<Basketball> instead of raw pointers and raw arrays, e.g.:
std::vector<Basketball> readFile(int & notFound);
Note that a vector knows its own size (e.g. you can call its size() method to query for it), so you don't need a separate reference parameter to store the size.
And, moreover, a vector automatically cleans up its content, thanks to its destructor. So, you don't put a burden on the caller to make an explicit call to delete[] to release the allocated array.
As an alternative, you could use a bool parameter meaning "not found", and pass the vector as non-const reference, e.g.:
// Returns false if not found, true if found
bool readFile(std::vector<Basketball>& v);
Or, depending on your design, you may even return a std::vector, and throw an exception in the not-found case.
Related
I'm trying to create a function called void find(int id, Student** s) that searches the array for the student with the id specified in parameter id, and returns that student pointer using parameter s. The task says I must use the parameter to return this data and to not use the return value.
I'm a little confused by what the last line means. I have this so far but the s == students[i] line causes the error: comparison between distinct pointer types ‘Student**’ and ‘Student*’ lacks a cast [
void StudentsArray::find(int id, Student** s){
for(int i = 0; i < studentsCount; ++i){
if(students[i]->getId() == id){
s=students[i];
}
}
}
I'm just a little confused on what I'm supposed to return and how I would go about doing so and would appreciate any help!
The second argument in the function says "A pointer to a pointer to Student"
To return it, you'll need to set it to a pointer of Student.
Taking a pointer of one of the student array is done like this: &student[i].
Once you have the pointer, you need to store somewhere, and you'll store it inside the given pointer-to-pointer by dereferencing it like this: *s
Put together, you'll need to *s = &student[i] to perform: "store in the memory area pointed by s the address of the student's item"
void StudentsArray::find(int id, Student** s){
*s = nullptr;
for(int i = 0; i < studentsCount; ++i){
if(students[i]->getId() == id){
*s = &students[i];
}
}
}
If this is disturbing at first, just remove a layer of indirection by writing:
void StudentsArray::find(int id, Student* & s) {
...
s = &student[i];
...
}
In that case, you are taking a reference (so if you modify it inside the function you're modifying it from the caller's site) to a pointer to student. When you assign it, it's like it's returned to the caller.
Why it's important
Sometimes, you need to be able to return more than one thing from a function. Either you build a structure holding the things and you return that but it's very painful to do and usually not very efficient, either you simply accept a pointer (or a reference) to these things and expect the function to fill them for you. From my own experience, this is what is done most of the time.
EDIT: Following remark from Tanveer Badar, it's good practice to expect the function to set the returned value to 0 (or better nullptr) if not found so you don't have to do it on the caller's site.
You could instead return the index where the match happened or -1 if none matched.
int StudentsArray::find(int id){
for(int i = 0; i < studentsCount; ++i){
if(students[i]->getId() == id){
return i;
}
}
return -1;
}
I'm playing around with pointers to understand this concept better
and wanted to ask
Why do i get null pointer as return for the second function?
and why it isn't possible to get the address 0x7fff15504044.
What is happening and where inside memory is the integer 5 stored,
when im working with it inside the function?.
#include <iostream>
using namespace std;
int* return_adress(int* input){ return input; }
int* return_adress_from_input(int input){ return &input; }
int main(){
int k = 3;
cout << return_adress(&k) << endl;
cout << return_adress_from_input(k) << endl;
}
Output:
0x7fff15504044
0
With int* return_adress_from_input(int input), input is a value copy of k in the caller. They are two different variables therefore with different addresses.
input goes out of scope conceptually once the closing brace of the function is reached.
The pointer &input then points to memory that you no longer own, and the behaviour of reading that pointer value (let alone dereferencing it) is undefined prior to C++14, and implementation defined from and including C++14.
Because you pass input by value, not by reference. Compiller first creates a local copy of input and then returns address of this local copy. To get the variable address use
int* return_adress_from_input(int& input){ return &input; }
In general, you get undefined behavior which can lead to returning nullptr in the particular case
On my PC i get
00AFFC80
00AFFBA8
so you are just lucky with zero return
struct mystruct{
int* x;
float *y;
string *z;
mystruct(int* a,float* b, string *c): x(a), y(b), z(c){}
};
void* create(){
int a = 1;
float b = 2.2;
string c = "aaa";
mystruct x(&a, &b, &c);
void* p = &x;
return p;
}
void print(void *p){
mystruct* p1 = static_cast<mystruct*>(p);
cout << *p1->x << " " << *p1->y << " "<<*p1->z<< endl;
}
int main(){
cout << sizeof(mystruct) << endl;
void* p1 = create();
print(p1);
return 0;
}
The output of the code is like: 24
1 2.76648e+19 \203\304 ]\303fffff.\204UH\211\345H\201\354\220H\211}\270H\211.
for which I suppose is: 24 1 2.2 aaa
I guess there is something wrong with the void* pointer casting, but I can not figure out why. Can someone help?
You creating undefined behaviour with this:
void* create(){
int a = 1;
float b = 2.2;
string c = "aaa";
mystruct x(&a, &b, &c);
void* p = &x;
return p;
}
There you initialize a mystruct with pointers to objects in the automatic storage scope (aka a local variable) of create. These objects cease to exist the very moment create is returned from and thus the pointers become invalid. Furthermore you're returning a pointer to a mystruct automatic storage object inside the create function as well. So that's kind of invoking undefined behaviour on top of undefined behaviour.
EDIT here's a proposed solution:
Stop using pointers inside the struct. It doesn't make sense to pass around pointers to int or float anyway, because pointers will always be larger than those. If you pass a pointer or a pointer to a function, either will be passed by copying the value, but with a pointer there's an extra indirection step. Where passing pointers to numeric types makes sense if you want to use them to pass a "reference" where the function can alter the values.
It also makes sense for passing pointers to structures so that not whole structures have to be copied around.
So I suggest you get rid of the pointers at a whole. You apparently do not yet understand how they work, and for that particular task you have there they are the wrong tool anyway.
To fully understand how pointers, values, and references work, I am making a basic C++ program that attempts to tamper with some static and dynamic arrays and understand exactly how they should be passed in.
First I generate a static array of 3 elements. I then pass it into a function that modifies all elements. I then pass it into another function with a slightly different signature, but can also alter the array's values.
Next I generate a dynamically sized array, pass it into a function by reference so that all of the values in this dynamically sized array can be altered.
The code is as follows:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void changeIndexStaticArrayMethod1(int* stat);
void changeIndexStaticArrayMethod2(int (&stat)[3]);
void changeIndexDynamicArrayMethod1(int* dyn, int size);
int main() {
const int MAX = 3;
int arr[MAX] = { 1,2,3 };
changeIndexStaticArrayMethod1(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << endl;
changeIndexStaticArrayMethod2(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
int SIZE;
cout << "Please choose a size for the array" << endl;
cin >> SIZE;
int *ne = new int[SIZE];
//Build array
for (int i = 0; i < SIZE; i++) {
ne[i] = i;
}
changeIndexDynamicArrayMethod1(ne, SIZE);
for (int i = 0; i < SIZE; i++) {
cout << "ne[" << i << "] = " << ne[i] << endl;
}
//To hang program
cin >> SIZE;
delete[] arr;
delete[] ne;
return 0;
}
void changeIndexStaticArrayMethod1(int* stat) {
stat[0] = 10;
stat[1] = 20;
stat[2] = 30;
}
void changeIndexStaticArrayMethod2(int (&stat)[3]) {
stat[0] = 40;
stat[1] = 50;
stat[2] = 60;
}
void changeIndexDynamicArrayMethod1(int* dyn, int size) {
for (int i = 0; i < size; i++) {
dyn[i] = i * 10;
}
}
All of the above code works how I want it to, I just have a few questions as to why (some of the methods of passing arrays by reference I have found on other SO questions).
In the changeIndexStaticArrayMethod1() and changeIndexDynamicArrayMethod1() functions, why are we able to use the dereference * operator for our array as reference? My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator. I know that with arrays, it is much different than using variables, but also, why will the following not work for single int variables:
void changeStaticNumber(int* num){
num = 100;
}
Obviously the above will work if we use &num and not int* num, and obviously I don't fully understand the relationship between pointers and arrays, but I cannot figure out why when we pass an array by reference, int* staticArray is ok.
Any explanation for these problems I am having would be much appreciated. Thanks.
why are we able to use the dereference * operator for our array as reference?
The * in C means many things. It can mean the unary indirection ("contents of") operator, it can mean the binary multiplication operator and it can mean a pointer declaration. The int* stat is a pointer declaration.
Since you aren't using the * to dereference the contents of the pointer inside that function, I'm not quite sure what you are asking.
When you take the array name of your array in main(), it "decays" into a pointer to the first element. So what those function do, is to take a pointer by value. If you dereference the pointer by typing *stat = something; you access the actual array in main.
Should you do something weird like changing the pointer itself, for example stat++;, then it will not affect the address used in main. You passed the pointer itself by value, so the pointer is a local copy.
My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator.
You can't really pass arrays by value in C or C++, without resorting to dirty tricks (storing them inside structs or classes). For example, had your function been written as void changeIndexStaticArrayMethod1(int stat[3]) it would still give you a pointer to the first element. It will not pass an array by value, as the syntax might trick you into believing.
why will the following not work for single int variables:
void changeStaticNumber(int* num){ num = 100; }
Because num is the pointer itself, not its contents. In order to write code like that, you could pass the variable by reference int& num. Behind the lines this is really the same thing as passing a pointer, just with simplified syntax.
To understand the relation between pointers and arrays better, start by reading this whole chapter: http://c-faq.com/aryptr/index.html (C and C++ are identical when it comes to pointers).
Let me see if I can take a stab at this.
Pointers are simply address holders. Once you do int * ptr = myarray; --- what you are in tern doing is storing the address of the pointer my array into ptr --- array names are actually pointers to the first memory location in the array. You can use pointer arithmetic to get at everything else for example myarray +1 will point you to the next location or myarray[1].
Passing by value is not very useful when you need to modify your array. Passing in by reference is essentially making a pointer to the array and passing that. Since arrays like vectors are contiguous blocks of memory you can index through them rather easily.
As far as your example goes void changeStaticNumber(int* num){ num = 100; } will not work because what you are attempting to do is store 100 into the pointer's address. If you deference num and make it void changeStaticNumber(int* num){ *num = 100; } it will work because you are actually going one step further and accessing the data that num is pointing to. When you use &num it is essentially the same thing - & just gives you the address of something.
For example if you want to point a pointer to an int what you would do is
int num = 5;
int *ptr = #
at this point in time ptr has the same address in num. To print out the data in num or that ptr is pointing to you need to dereference or go one step further as I like to tell myself and dereference to so cout << *ptr;
In both changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 you are not passing an array there is no pass by reference (which only happens if the parameter type is a reference type -- i.e. with &). The parameter has type int * (pointer to int). You are passing a pointer to int by value. There is no "dereference operator" in either function.
ne is already an int *, so passing it is nothing special. arr is an int [3], an array, not a pointer. In C, when an array-of-T is used in a context that expects a pointer-to-T, it is implicitly converted (without you needing to do anything) to a pointer to its first element. So when you do, changeIndexStaticArrayMethod1(arr), the compiler gets a pointer to the first element of arr, and passes that to the function.
The [] operator works on pointers. a[i] is always guaranteed to be the same as *(a + i). Inside both the changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 functions, [] is used to access subsequent elements using a pointer to the first element.
still working at C++, but this came up in my book and I don't understand what it's for:
MyClass * FunctionTwo (MyClass *testClass) {
return 0;
}
My question is what is the signifigance of the first indirection operator
(MyClass *[<- this one] FunctionTwo(MyClass *testClass))?
I tried making a function like it in codeblocks, with and without the first * and I didn't see any difference in the way it ran or it's output:
int *testFunc(int *in) {
cout << in << endl;
cout << *in << endl;
return 0;
}
int testFuncTwo(int *in) {
cout << in << endl;
cout << *in << endl;
return 0;
}
I couldn't find anywhere that explained about it in my book.
Thanks,
Karl
The MyClass * means that this function returns a pointer to a MyClass instance.
Since the code is actually returning 0 (or NULL) this means that any caller to this function gets back a NULL pointer to a MyClass object.
I think the following are better examples:
int *testFunc(int *in) {
cout << "This is the pointer to in " << in << endl;
cout << "This is the value of in " << *in << endl;
return in;
}
int testFuncTwo(int *in) {
cout << "This is the pointer to in " << in << endl;
cout << "This is the value of in " << *in << endl;
return *in;
}
void test() {
int a = 1;
cout << "a = " << a;
int output = *testFunc(&a); // pass in the address of a
cout << "testFunc(a) returned " << output;
output = testFuncTwo(&a); // pass in the address of a
cout << "testFuncTwo(a) returned " << output;
}
Apologies, but I've not done C++ in years but the syntax may be a little off.
The general format for a function that takes a single value and returns a single value in C++ is:
return_type function name ( parameter_type parameter_name )
In your case, return_type is MyClass *, which means "pointer to MyClass"
In addition, in your case, parameter_type is also MyClass *.
In other words, your code could be rewritten as:
typedef MyClass *PointerToMyClass;
PointerToMyClass FunctionTwo (PointerToMyClass testClass)
{
return 0;
}
Does that look more familiar?
Given the nature of the question, I'm going to provide a somewhat crude answer.
A pointer points to something:
int x = 123; // x is a memory location (lvalue)
int* y = &x; // y points to x
int** z = &y; // z points to y
In the above code, z points to y which points to x which stores an integral, 123.
x->y->z[123] (this is not code, it's a
text diagram)
We can make y point to another integer if we want or NULL to make it point to nothing, and we can make z point to another pointer to an integer if we want or NULL to make it point to nothing.
So why do we need pointers which point to other things? Here's an example: let's say you have a simple game engine and you want to store a list of players in the game. Perhaps at some point in the game, a player can die by having a kill function called on that player:
void kill(Player* p);
We want to pass a pointer to the player, because we want to kill the original player. Had we done this instead:
void kill(Player p);
We would not kill the original player, but a copy of him. That wouldn't do anything to the original player.
Pointers can be assigned/initialized with a NULL value (either NULL or 0) which means that the pointer will not point to anything (or cease to point to anything if it was pointing to something before).
Later you will learn about references which are similar to pointers except a pointer can change what it points to during its lifetime. A reference cannot, and avoids the need to explicitly dereference the pointer to access the pointee (what it's pointing to).
Note: I kind of skirted around your original question, but the sample code you provided has no inherent meaningful behavior. To try to understand that example without first understanding pointers in a general sense is working backwards IMHO, and you'd be better to learn this general theory first.
If you had something like int * Function() this would return a pointer to an integer. MyClass * just means that the function is going to return a pointer to an object of type MyClass. In c++ user defined objects are treated as first-class-objects, so once you create your own objects they can be passed as a parameter, returned from a subroutine, or assigned into a variable just like the standard types.
In the code blocks you posted there will be no difference in the output to the console because the thing you have changed is the type that the function returns (which is not used), the contents of the functions are identical.
When you define:
int *testFunc(int *in)
You are defining a function which returns a pointer to an int variable.
int testFuncTwo(int *in)
Returns just an int variable.
Zero in this case is undergoing an implicit cast - the first function returns (int*) 0, the second just 0. You can see this implicit cast in action if you change the prototype of your example function from returning a MyClass* to just returning a MyClass - if there's no operator int method in MyClass, you'll get a nice error.