Best approach with sort in place algorithms [duplicate] - php

In C++ if you pass a large array to a function, you need to pass it by reference, so that it is not copied to the new function wasting memory. If you don't want it modified you pass it by const reference.
Can anyone verify that passing by reference will save me memory in PHP as well. I know PHP does not use addresses for references like C++ that is why I'm slightly uncertain. That is the question.

The following does not apply to objects, as it has been already stated here. Passing arrays and scalar values by reference will only save you memory if you plan on modifying the passed value, because PHP uses a copy-on-change (aka copy-on-write) policy. For example:
# $array will not be copied, because it is not modified.
function foo($array) {
echo $array[0];
}
# $array will be copied, because it is modified.
function bar($array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
# This is how bar shoudl've been implemented in the first place.
function baz($array) {
$temp = $array[0] + 1;
echo $temp + $array[1];
}
# This would also work (passing the array by reference), but has a serious
#side-effect which you may not want, but $array is not copied here.
function foobar(&$array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
To summarize:
If you are working on a very large array and plan on modifying it inside a function, you actually should use a reference to prevent it from getting copied, which can seriously decrease performance or even exhaust your memory limit.
If it is avoidable though (that is small arrays or scalar values), I'd always use functional-style approach with no side-effects, because as soon as you pass something by reference, you can never be sure what passed variable may hold after the function call, which sometimes can lead to nasty and hard-to-find bugs.
IMHO scalar values should never be passed by reference, because the performance impact can not be that big as to justify the loss of transparency in your code.

The short answer is use references when you need the functionality that they provide. Don't think of them in terms of memory usage or speed. Pass by reference is always going to be slower if the variable is read only.
Everything is passed by value, including objects. However, it's the handle of the object that is passed, so people often mistakenly call it by-reference because it looks like that.
Then what functionality does it provide? It gives you the ability to modify the variable in the calling scope:
class Bar {}
$bar = new Bar();
function by_val($o) { $o = null; }
function by_ref(&$o) { $o = null; }
by_val($bar); // $bar is still non null
by_ref($bar); // $bar is now null
So if you need such functionality (most often you do not), then use a reference. Otherwise, just pass by value.
Functions that look like this:
$foo = modify_me($foo);
sometimes are good candidates for pass-by-reference, but it should be absolutely clear that the function modifies the passed in variable. (And if such a function is useful, often it's because it really ought to just be part of some class modifying its own private data.)

In PHP :
objects are passed by reference1 -- always
arrays and scalars are passed by value by default ; and can be passed by reference, using an & in the function's declaration.
For the performance part of your question, PHP doesn't deal with that the same way as C/C++ ; you should read the following article : Do not use PHP references
1. Or that's what we usually say -- even if it's not "completely true" -- see Objects and references

Related

Why do I have to use the reference operator (&) in a function call?

Setup
I am borrowing a function from an open source CMS that I frequently use for a custom project.
It's purpose is not important to this question but if you want to know it's a simple static cache designed to reduce database queries. I can call getObject 10 times in one page load and not have to worry about hitting the database 10 times.
Code
A simplified version of the function looks like this:
function &staticStorage($name, $default_value = NULL)
{
static $data = array();
if (isset($data[$name])
{
return $data[$name];
}
$data[$name] = $default_value;
return $data[$name];
}
This function would be called in something like this:
function getObject($object_id)
{
$object = &staticStorage('object_' . $object_id);
if ($object)
{
return $object;
}
// This query isn't accurate but that's ok it's not important to the question.
$object = databaseQuery('SELECT * FROM Objects WHERE id = #object_id',
array('#object_id => $object_id'));
return $object;
}
The idea is that once I call static_storage the returned value will update the static storage as it is changed.
The problem
My interest is in the line $object = &staticStorage('object_' . $object_id); Notice the & in front of the function. The staticStorage function returns a reference already so I initially did not include the reference operator preceding the function call. However, without the reference preceding the function call it does not work correctly.
My understanding of pointers is if I return a pointer php will automatically cast the variable as a pointer $a = &$b will cause $a to point to the value of $b.
The question
Why? If the function returns a reference why do I have to use the reference operator to precede the function call?
From the PHP docs
Note: Unlike parameter passing, here you have to use & in both places - to indicate that you want to return by reference, not a copy, and to indicate that reference binding, rather than usual assignment, should be done for $myValue.
http://php.net/manual/en/language.references.return.php
Basically, its to help the php interpreter. The first use in the function definition is to return the reference, and the second is to bind by reference instead of value to the assignment.
By putting the & in the function declaration, the function will return a memory address of the return value. The assignment, when getting this memory address would interpret the value as an int unless explicitly told otherwise, this is why the second & is needed for the assignment operator.
EDIT: As pointed out by #ringø below, it does not return a memory address, but rather an object that will be treated like a copy (technically copy-on-write).
The PHP doc explains how to use, and why, functions that return references.
In your code, the getObject() function needs also a & (and the call as well) otherwise the reference is lost and the data, while usable, is based on PHP copy-on-write (returned data and source data point both to the same actual data until there is a change in one of them => two blocks of data having a distinct life)
This wouldn't work (syntax error)
$a = array(1, 2, 3);
return &$a;
this doesn't work as intended (no reference returned)
$a = array(1, 2, 3);
$ref = &$a;
return $ref;
and without adding the & to the function call as you said, no reference returned either.
To the question as to why... There doesn't seem to be a consistent answer.
if one of the & is missing PHP treats data as if it isn't a reference (like returning an array for instance) with no warning whatsoever
here some strangeness associated to functions returning references
PHP evolved during the years but still inherits some of the initial poor design choices. This seems to be one of them (this syntax is error prone as one may easily miss one &... and no warning ahead... ; also why not directly return a reference like return &$var;?). PHP made some progress but still, traces of poor design subsist.
You may also be interested in this chapter of the doc linked above
Do not use return-by-reference to increase performance. The engine will automatically optimize this on its own. Only return references when you have a valid technical reason to do so.
Finally, it's better not to look too much for equivalences between the pointers in C and the PHP references (Perl is closer than PHP in this regard). PHP adds a layer between the actual pointer to data and variables and references point rather to that layer than the actual data. But a reference is not a pointer. If $a is an array and $b is a reference to $a, using either $a or $b to access the array is equivalent. There is no dereference syntax, a *$b for instance like in C. $b should be seen as an alias of $a. This is also the reason a function can only return a reference to a variable.

Is it efficient to return an array in php?

I'm fairly new to PHP; most of my programming experience so far has been in C++. So, naturally, I get concerned about efficiency. In C++ you never ever ever return an object or an array at the end of a function, but if you need the data, you just return a pointer.
So my question is: is it bad for efficiency to be using arrays as return values, or does PHP just use a pointer in the background and just not show me for convenience?
PHP returns a reference if it's optimal for the interpreter to do so. Normally parameters passed to functions are copied, though you pass a parameter by reference and therefore get a return value by reference like so:
function blah(&$foo) {
$foo = array();//or whatever
//note no return statement
}
//elsewhere
$x = "whatever";
blah($x);
//$x is now an array.
Because of &, $foo is treated as a reference, and so modifications to that variable are treated as modifications to the reference.
Or you can force the function to return a reference:
function &blah() {
//some stuff
return $foo;//goes back as a reference
}
This latter shouldn't, according to the docs, be done unless you have a non-optimization reason to do so.
That said, PHP isn't terribly efficient, and worrying about these things is generally premature - unless you're seeing an actual performance bottleneck in your code.

What does the ampersand sign(&) means in this method? [duplicate]

I'm using the Facebook library with this code in it:
class FacebookRestClient {
...
public function &users_hasAppPermission($ext_perm, $uid=null) {
return $this->call_method('facebook.users.hasAppPermission',
array('ext_perm' => $ext_perm, 'uid' => $uid));
}
...
}
What does the & at the beginning of the function definition mean, and how do I go about using a library like this (in a simple example)
An ampersand before a function name means the function will return a reference to a variable instead of the value.
Returning by reference is useful when
you want to use a function to find to
which variable a reference should be
bound. Do not use return-by-reference
to increase performance. The engine
will automatically optimize this on
its own. Only return references when
you have a valid technical reason to
do so.
See Returning References.
It's returning a reference, as mentioned already. In PHP 4, objects were assigned by value, just like any other value. This is highly unintuitive and contrary to how most other languages works.
To get around the problem, references were used for variables that pointed to objects. In PHP 5, references are very rarely used. I'm guessing this is legacy code or code trying to preserve backwards compatibility with PHP 4.
This is often known in PHP as Returning reference or Returning by reference.
Returning by reference is useful when you want to use a function to
find to which variable a reference should be bound. Do not use
return-by-reference to increase performance. The engine will
automatically optimize this on its own. Only return references when
you have a valid technical reason to do so.
PHP documentation on Returning reference
A reference in PHP is simply another name assigned to the content of a variable. PHP references are not like pointers in C programming, they are not actual memory addresses, so they cannot be used for pointer arithmetics.
The concept of returning references can be very confusing especially to beginners, so an example will be helpful.
$populationCount = 120;
function &getPopulationCount() {
global $populationCount;
return $populationCount;
}
$countryPopulation =& getPopulationCount();
$countryPopulation++;
echo "\$populationCount = $populationCount\n"; // Output: $populationCount = 121
echo "\$countryPopulation = $countryPopulation\n"; //Output: $countryPopulation = 121
The function getPopulationCount() defined with a preceding &, returns the reference to the content or value of $populationCount. So, incrementing $countryPopulation, also increments $populationCount.

When is it good to use pass by reference in PHP?

In C++ if you pass a large array to a function, you need to pass it by reference, so that it is not copied to the new function wasting memory. If you don't want it modified you pass it by const reference.
Can anyone verify that passing by reference will save me memory in PHP as well. I know PHP does not use addresses for references like C++ that is why I'm slightly uncertain. That is the question.
The following does not apply to objects, as it has been already stated here. Passing arrays and scalar values by reference will only save you memory if you plan on modifying the passed value, because PHP uses a copy-on-change (aka copy-on-write) policy. For example:
# $array will not be copied, because it is not modified.
function foo($array) {
echo $array[0];
}
# $array will be copied, because it is modified.
function bar($array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
# This is how bar shoudl've been implemented in the first place.
function baz($array) {
$temp = $array[0] + 1;
echo $temp + $array[1];
}
# This would also work (passing the array by reference), but has a serious
#side-effect which you may not want, but $array is not copied here.
function foobar(&$array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
To summarize:
If you are working on a very large array and plan on modifying it inside a function, you actually should use a reference to prevent it from getting copied, which can seriously decrease performance or even exhaust your memory limit.
If it is avoidable though (that is small arrays or scalar values), I'd always use functional-style approach with no side-effects, because as soon as you pass something by reference, you can never be sure what passed variable may hold after the function call, which sometimes can lead to nasty and hard-to-find bugs.
IMHO scalar values should never be passed by reference, because the performance impact can not be that big as to justify the loss of transparency in your code.
The short answer is use references when you need the functionality that they provide. Don't think of them in terms of memory usage or speed. Pass by reference is always going to be slower if the variable is read only.
Everything is passed by value, including objects. However, it's the handle of the object that is passed, so people often mistakenly call it by-reference because it looks like that.
Then what functionality does it provide? It gives you the ability to modify the variable in the calling scope:
class Bar {}
$bar = new Bar();
function by_val($o) { $o = null; }
function by_ref(&$o) { $o = null; }
by_val($bar); // $bar is still non null
by_ref($bar); // $bar is now null
So if you need such functionality (most often you do not), then use a reference. Otherwise, just pass by value.
Functions that look like this:
$foo = modify_me($foo);
sometimes are good candidates for pass-by-reference, but it should be absolutely clear that the function modifies the passed in variable. (And if such a function is useful, often it's because it really ought to just be part of some class modifying its own private data.)
In PHP :
objects are passed by reference1 -- always
arrays and scalars are passed by value by default ; and can be passed by reference, using an & in the function's declaration.
For the performance part of your question, PHP doesn't deal with that the same way as C/C++ ; you should read the following article : Do not use PHP references
1. Or that's what we usually say -- even if it's not "completely true" -- see Objects and references

Is there a need to pass variable by reference in php5?

With PHP5 using "copy on write" and passing by reference causing more of a performance penalty than a gain, why should I use pass-by-reference? Other than call-back functions that would return more than one value or classes who's attributes you want to be alterable without calling a set function later(bad practice, I know), is there a use for it that I am missing?
You use pass-by-reference when you want to modify the result and that's all there is to it.
Remember as well that in PHP objects are always pass-by-reference.
Personally I find PHP's system of copying values implicitly (I guess to defend against accidental modification) cumbersome and unintuitive but then again I started in strongly typed languages, which probably explains that. But I find it interesting that objects differ from PHP's normal operation and I take it as evidence that PHP"s implicit copying mechanism really isn't a good system.
A recursive function that fills an array? Remember writing something like that, once.
There's no point in having hundreds of copies of a partially filled array and copying, splicing and joining parts at every turn.
Even when passing objects there is a difference.
Try this example:
class Penguin { }
$a = new Penguin();
function one($a)
{
$a = null;
}
function two(&$a)
{
$a = null;
}
var_dump($a);
one($a);
var_dump($a);
two($a);
var_dump($a);
The result will be:
object(Penguin)#1 (0) {}
object(Penguin)#1 (0) {}
NULL
When you pass a variable containing a reference to an object by reference, you are able to modify the reference to the object.

Categories