void (int a[]) {
a[5] = 3; // this is wrong?
}
Can I do this so that the array that is passed in is modified?
Sorry for deleting, a bit new here...
I have another question which might answer my question:
If I have
void Test(int a) {
}
void Best(int &a) {
}
are these two statements equivalent?
Test(a);
Best(&a);
void Test(int a[])
{
a[5] = 3;
}
just alternate syntax for:
void Test(int* a)
{
*(a+5) = 3;
}
No array is passed, just a pointer. The original array is modified.
As for your second revision, given:
void Test(int a)
{
}
void Best(int &a)
{
}
then
Test(aa); // Passes aa by value. Changes to a in Test() do not effect aa
Best(aa); // Passes aa by reference; Changes to a DO effect aa
Best(&aa); // Is a syntax error: Passing a pointer instead of an int.
If you get the variable not by reference and not by pointer, it means that the function is essentially isolated, getting an ad-hoc copy of a. No matter what you do (without trying to hack the stack or things like that) you wouldn't have access to that value in the calling context.
If you know something about the calling context, you may be able to do things based on some anticipation of stack contents, but it's generally a bad idea.
If your method takes a[] which is essentially a*, then yes, you can alter the contents of the cell that a points to, but you won't be able to alter a (the pointer) itself to point at something else.
Nope.
Your options for altering a value from outside the function are call by reference f(int& a), call by pointer f(int* a), and using a global (shudder...) variable.
Read the answer given here about the difference of int[] and int* in a parameter list: Difference between char* and char[] . I've really put so much love into that answer! :)
Regarding your question about your Test and Best functions, James Curran provided an excellent answer.
Your original Function should work.
If you give it a name:
#include <iostream>
// Arrays always de-generate to pointers.
void plop(int a[]) // Make sure this function has a name.
{
a[5] = 3;
}
int main()
{
int test[] = { 1,1,1,1,1,1,1,1};
plop(test);
std::cout << test[5] << std::endl;
}
This is because arrays always de-generate into pointers when passed as an argument to a function. So this should always work as expected. Assuming you don't index beyond the end of the array. Inside plop there is no way to determine the size of the array passed.
The primary motivator for passing arrays by reference is to prevent stack overflows and needless copying of large objects. For example, imagine if I had a function like this:
void foo(int x[500000000000]);
The stack would probably overflow the first time you called the function if all arrays were passed by value (but of course this is an obvious exaggeration).
This will become useful when using object-oriented methods. Suppose instead of an array, you had this:
void foo(SomeClass x);
where SomeClass is a class with 500000000000 data members. If you called a method like this, the compiler would copy x bit by bit, which would be a very long process to say the least. The same concept as you use in arrays still applies, but you have to specify that this is to be used by reference manually:
void foo(SomeClass &x);
(and don't go trying to create a 500000000000 element array to begin with unless you have a 64 bit machine and lots of RAM)
Related
I am trying to find out using the below code with sort an array in asscending order. And I find method 1,2,3,4 all get the same result:1234.
Which method is the best?
And when and why should should I use pointer /reference? Thanks you.
Using & to call, and * in function parameter
Just used * in function parameter
Just used & in function parameter
nothing:
#include <iostream>
using namespace std;
void swap(int a,int b){
int t;
t=a;
a=b;
b=t;
}
void main(){
int a[]={1,2,3,4};
for (int i=1; i<3; i++)
for (int j=3; j>i;j--)
if(a[j]<a[j-1])
swap(a[j],a[j-1]);
cout << a[0] <<a[1]<<a[2]<<a[3];
}
Your first two versions are identical. They both explicitly pass a pointer in to the function.
Your third version has the same semantics, but different syntax. References can be seen as pointers with nicer syntax.
Your fourth version doesn't actually swap the variables you pass in because you pass by value, so they are copied.
I would prefer the third version as it is clearer.
Generally, references are more of a convenience thing. They allow the programmer to pass objects by reference without explicitly saying they want to do so
For example, this code
// C-style pointers
some_func(int* x, int* y)
{
(*x)++;
(*y)++;
}
...
int x = 5, y = 8;
some_func(&x, &y);
// x == 6 and y == 9
Is effectively equal to this code
// C++-style references
some_func(int& x, int& y)
{
x++;
y++;
}
...
int x = 5, y = 8;
some_func(x, y);
// x == 6 and y == 9
Both achieve the same result.
Also, in the case with classes/structs, references allow you to have direct access to class/struct members without having to type that stupid arrow (->):
class Example
{
public:
Example();
int x;
int y;
}
...
void do_something(Example& ex)
{
ex.x++;
ex.y++;
}
instead of
class Example
{
public:
Example();
int x;
int y;
}
...
void do_something(Example* ex)
{
ex->x++;
ex->y++;
}
Please note that references used in this manner are a C++ feature only (there is no support for this in C). In C++ you have the choice of using either pointers or references, but IMHO references look 'cleaner' and require less typing (thus reducing the risk of RSI).
I don't see a difference between 1. and 2.. But in general:
Passing pointers is passing an address to a variable. Then you modify something under this address using dereference i.e. *a.
Same.
Is passing via reference, it is basically equivalent of passing pointers with nicer syntax. There are of course some "minor" (from a beginner's point of view) differences, such as, you cannot make an empty reference (nullptr).
Is passing by value, which does not operate on original operands but on their copies. At the function call, temporary copies of arguments are made. This means, you won't see changes to the argument outside of the function.
The general order of preference is:
Use references, or const references.
If you need to make a copy of the object anyways, pass by value.
Smart pointers.
Pointers. Normal user should almost never need to resort to this.
Using references is preferred, because c++ prefers value-semantics. In other words, treating things like variables, i.e. not handlers/pointers. So when you pass a variable to a function, you type it naturally, even if you want to change it. You want to use the object, you pass the object. You don't care that under the hood it uses handlers.
Pointers are generally reserved for operations which deal with ownership of objects.
Separating pointers and references in such way makes it possible to express separate semantics with separate syntax. This makes code more readable.
First of all, I would like to point out that you shouldn't have used
int a[]={1,2,3,4};
in your code, because your program will always display 1234 even if your swap function does not work well. Therefore, you should use something like
int a[]={2,4,1,3};
Secondly, method 1 and method 2 are exactly same. There's no difference at all.
Thirdly, method 4 does not work properly, because the data in the array 'a' hasn't been modified. This happens because you have passed the variables 'by value' rather than 'by reference'. You are getting 1234 as output because that's what you have assigned to the array.
Finally, the only choice you have is between 'method 1' and 'method 3'.
I would suggest 'method 3' because it is simpler to use and less prone to confusion (and errors) as compared to 'method 1'.
In some cases, passing by reference allows the compiler to keep a register based variable in that same register in the called function (as opposed to storing the value in local memory and passing an address to that local memory to the called function).
I am using std::thread to execute multiple threads. I pass a pointer to an array as an argument, something akin to:
my_type* rest[count];
//Fill rest array
std::thread(fnc, rest, count);
The issue I seem to be having, is that somewhere along the way, the pointer values in 'rest' get corrupted. I print out the pointer values before the call to std::thread, and first thing in the function that std::thread calls on my behalf, and the values do not match. It seems fairly random, sometimes they will match, and sometimes not (and a segfault results when the latter happens).
I know (from what little I could find on the topic) that std::thread copies the arguments, and I am thinking that my issue stems from this, and that there is a special function std::ref() that allows it to pass references, but none of them mention pointers specifically. I have tried various techniques to attempt to pass this array with std::ref() but I have yet to solve the issue.
Am I correct in thinking that this could be the cause of my issue, or am I barking up the wrong tree?
if gets converted in some fashion (the array pointer, not the contents) then I would have a problem.
Yes, that's exactly what happens.
It's often incorrectly said that arrays are just pointers. The truth of the matter is that whenever you declare a function that takes an array:
void foo(int x[10]);
The declaration is 'adjusted' so that the parameter is a pointer:
void foo(int *x); // C++ can't tell the difference between this and the first declaration
and when you call the function:
int x[10];
foo(x);
There's an implicit conversion equivalent to the following:
int x[10];
int *tmp = &x[0];
foo(tmp);
So what happens is that you have a block of memory containing your pointers to long lived objects:
my_type *rest[count] = {new my_type, new my_type, new my_type};
You pass a pointer to that block of memory to the thread:
thread(fnc, &rest[0], count);
Then when the function returns rest goes out of scope, and that block of memory is no longer valid.
Then the thread follows the pointer to the block of memory and reads garbage. If by some chance it does read the correct array contents then it can access the long lived objects just fine. The problem is getting the pointers to the long lived objects from the corrupt block of memory where rest used to be on the stack.
Is there a way to suppress this behavior?
In most cases the only thing that makes sense is not use raw arrays as function parameters. You can wrap a raw array in a struct and get the sensible behavior:
struct int_array {
int x[10];
};
void foo(int_array x);
int main() {
int_array x = {1,2,3,4,5,6,7,8,9,0};
foo(x); // the array is copied rather than getting strangely converted
}
This is pretty much exactly what std::array does, so you're better off using it.
In cases where you don't want a copy of the array you can take a reference to the array:
int foo(int (&x)[10]);
This gives you essentially the same behavior as the weird 'adjustments' and implicit conversions that are done behind your back with int foo(int x[10]); foo(x);. The benefit here is that it's explicit and that you get type checking on the size of the array. That is, due to the 'adjustment' the following does not result in a compiler error:
int foo(int x[10]);
int x[3];
foo(x);
Whereas this will:
int foo(int (&x)[10]);
int x[3];
foo(x); // the implicit conversion to &x[0] does not get happen when the function takes a reference to array
Just so you be aware of the risk of your code, try execute this:
#include <thread>
#include <iostream>
void f() { std::cout << "hello" << std::endl; }
int main()
{
{
auto t = std::thread(f);
std::cout << "0" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "1" << std::endl;
}
std::cout << "2" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(400));
std::cout << "3" << std::endl;
}
You'll see 2 and 3 never get to output, because the application is aways terminated.
In truth, it's more subtle, since at my sample, I've moved the thread to t. Resembling your original sample and not assigning the thread to any variable, there's no early termination, but "hello" never gets to output. (probably there was an optimization to eliminate the temporary, since it's never used; it just got destroyed before getting joinable; or who knows...)
This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 9 years ago.
Some of methods that I see in C++ code are of this structure:
void Class::method1(int &a);
and are called like this:
int a;
class->method1(a);
But sometimes I see structures like:
void Class2::method2(int* a);
And these methods are called like this:
int a;
class2->method2(&a);
I understand that in the first case the method accepts an address of a variable, and in the second - pointer to a variable, right?
Could someone explain to me what is the difference between these two approaches, and when to use which?
Also, in the first example, it seems that a method can be taking "int& a" or "int a", and in both cases we would call it the same way: int a; class->method1(a); ? This seems confusing.
Thanks.
void Class::method1(int &a);
This is passing by reference.
void Class2::method2(int* a);
This is passing the pointer. In class2->method2(&a);, & is the address of operater.
First one is called using a reference to a variable, second one - using a pointer. There are some difference between the two concepts. I encourage you to google this, but the most important ones I can think of right now are that a reference can not be constructed without pointing to an existing object and that a pointer can be NULL.
void Class::method1(int &a) means you are passing a by reference and the caller can expect a to be modified.
void Class2::method2(int* a) means you are passing a by pointer and the caller can expect the thing to which a points to be modified.
Personally I don't like pass by reference since the caller doesn't quickly know if a will be modified as the calling syntax for pass by reference and pass by value are identical. Passing by constant reference void Class::method1(const int &a) is better still since then a cannot be modified and you can gain an efficiency in not taking value copies if a is a large object.
However many folk differ in their opinion and say that you should pass by pointer if the function allows the pointer to be null; i.e. can your function do something useful without a inputted?
In the first case, the method accept a reference to the variable.
It means that if a is modified inside the method1, it will be modified after the function returns.
In the second case, it accepts a pointer to the variable. A pointer is the memory adress of the variable. It's what the & retrieves : The address (aka a pointer to a).
Both type have essentially the same purpose : Being able to modify a variable of a different scope.
See that example :
void fooPointer (int* pointer) {
*pointer += 1;
}
void fooReference (int& reference) {
reference += 1;
}
int main () {
int a = 0;
std::cout << a; // Ouputs 0
fooPointer (&a);
std::cout << a; // Outputs 1
fooReference (a);
std::cout << a; // Outputs 2
}
As you can see, both allow you to do the same here. But using references is usually easier and more readable, because everything is done implicitly, so you don't have to reference (*) or dereference (&) your variables.
What is the difference in the following code:-
int a;
int *p;
p=&a;
function(p);
and
int a;
function(&a);
I was reading a book where sometimes they have used the first code and sometimes the other. Its not a good book though (by a local author).
Will both codes work the same way or is there any difference?
Also is there any difference in terms of efficiency and does it matter that much?
Thanks
For a reference, the object must be already existing in order to reference it. As for a pointer, the object does not need to be already existing when declaring a pointer
Example:
int &i = 10; //Invalid
const int &i = 10; //Valid
also
you cannot declare an array of references:
int &tab[] = {2,3}; //Invalid
int * tab[] = {2,3}; //Valid
In practice, reference are mostly used as functions parameters and return values;
As far as I know compiler implements references as pointers. So there should be no difference in performance. But references are more strict and can protect you from making mistakes. For example you can't rebind references or can't perform arithmetic with them
Also some people prefere to pass pointers to the function that modify object. For example
void changeVal(int *p)
{
*p = 10;
}
They say it's more readable when you see:
changeVal(&var)
than
changeVal(var);
EDIT
You can think of reference as another name of the object it refers to. So all the changes made to reference are applied to the object. Here is an example:
void foo_copy(int a) //pass by copy
{
a = 10; //changes copy
}
void foo(int &a) //bass by reference
{
a = 10; //changes passed value
}
void foo(int *a) //pass an adress of a
{
(*a) = 10; //change a value pointed by a
a = nullptr; //change a (the pointer). value is not affected
}
In above two approaches, Both are using pointers, there is no difference except memory equal to sizeof(int *) will be allocated on stack for "int *p".
In case of call by reference, Refer. It seems you are beginner and learning things, you will come to know more about passing by reference and its use more while using copy constructor in classes.
The two code snippets should be equivalent when compiled with a modern compiler. The extra declaration and assignment (p=&a;) is optimised away.
Is it possible to define a function which will make the argument refer to another (already existing) object after it returns without using pointers, etc? Again, this can't just change the existing object by using a copy constructor or assignment operator or anything. The outside object would refer to a different block of memory when the function returned.
For example:
int x;
void change(int& blah) {
blah = x; // I don't want to change blah's value to x's value, I want to make blah refer to x outside the function
}
void main() {
int something = 0;
change(something);
assert(&x == &something);
}
Regardless of the method used, the function must be called like
change(x);
Without applying any special operator or function to the argument before calling the function. I don't know if this is possible, but it would make very cool things possible if it is. If it's not, I would also like to know why.
No, because something and x are different objects. They don't refer to different objects. They don't point to different objects. They are different objects.
To change where something points, that something needs to be a pointer. If you have a pointer, you can do this:
int x;
void change(int*& p)
{
p = &x;
}
int main()
{
int something = 0;
int* pointer = &something; // pointer points to 'something'
change(pointer); // now pointer points to 'x'
assert(&x == pointer);
}
Nope definitely not possible. Both regular variables like int x and references variables like int &y(...) and arrays are not reseatable, i.e. they always will use/point to the same chunk of memory.
To obtain the functionality you require, you really need to either use a pointer, or an abstraction of pointers. It's not possible otherwise.
As an attempt at an explanation, here goes (not entirely correct, and grossly simplified, but good enough to get the idea):
When you declare a variable like int x, you are really asking for the compiler to associate x with a specific region of memory. So, for example, suppose x is associated the four-byte starting at 0x439FC2. Since the compiler knows that x should always refer to 0x439FC2, than any use of x can really be replaced by looking up those memory cells, and loading them into registers, pushing them onto the stack, or whatever. Anyways, the end result is that the variable name x is pretty much replaced by the number 0x439FC2. So the reason you can't move x around is that you can't make that memory address refer to a different location in memory.
Again, that explanation is simplified and not entirely true, but it is the "intuitive" way of reasoning about automatically allocated variables.
You want to use a reference to a pointer:
void change(int &* blah, int * x){
blah = x;
}
int * num1;
int num2 = 2;
change( num1, &num2 ); //num1 now points to num2