开发者

(How) should I use object references?

Consider an example:

An application library that handles company's staff. Staff details are stored in a CSV file (please, do not judge this, as this is only used as an example).

Classes handling the staff info are (code very simplified just to give you the picture):

class St开发者_运维问答aff {
    /* array containing all Staff_Emplyee objects naturally (number) indexed */
    public $employees;
    /* array containing all Staff_Employee objects $name indexed */
    public $employees_names;
    /* array containing all Staff_Team objects naturally indexed */
    public $teams;
    /* array containing all Staff_Team objects $name indexed */
    public $teams_names;

    /* parses CSV file
     * creates new Staff_Employee objects
     * creates new Staff_Team objects
     * adds references to each Staff_Employee::$managers and Staff_Employee::$team
     * adds references to Staff_Team::$managers and Staff_Team::$staff */
    public __construct();

    /* returns a single Staff_Employee object */
    public get_employee($name) {};

    /* returns a single Staff_Team object */
    public get_team($name) {};
}


class Staff_Employee {
    /* string */
    public $name;
    /* array containing all Employee's managers as Staff_Employee objects */
    public $managers;
    /* Staff_Team object of the team the Employee is in */
    public $team;
}

class Staff_Team {
    /* string */
    public $name;
    /* array of all managers in the team (Staff_Employee objects) */
    public $managers;
    /* array of all non-managers in the team (Staff_Employee objects) */
    public $staff;
}

Now, at the moment there are no references used in the application. All object variables are passed-by-value. I thought this could potentially have some overhead. So once all Employee and Team objects are created I have simply tried changing all calls to those to references, e.g.:

$team1->managers[] = &$employee1;
$employee0->managers[] = &$employee1;

But this momentarily increased memory usage which was surprising to me. The example I'm using has only 200 worth of staff, but I can imagine that when having to deal with enterprises this can go up to thousands or even more and the memory usage would grow even more.

When I was thinking of this example, I tried to mimic ORM where I could do something like this:

$team->staff[n]->managers[n]->name; // infinite chaining?

Ideally the "proper" (initial?) objects would only be stored in Staff::$employees and Staff::$teams, so then Staff::$teams_names['Team Name'] would be a reference to Staff::$teams[n]. Similarly Staff_Team::$managers would be an array of references to Staff::$employees, etc.

But as I mentioned - as soon as I start using references memory usage rises.

Question(s):

So how should I handle this then?

Should I use pass-by-reference and don't worry about memory usage, or should I use pass-by-value?

Which one's better in this case and why?

Note1: I (think I) do understand the difference between passing an object by value and by reference. I'm only asking which one's better in this example.

Note2: There might be some manipulation to Staff_Employee object after it's created. Probably very minimal though.


Short answer: Don't use ampersands, "pass-by-value" (which confusingly enough, is referred as pass-by-reference in other languages.)

Longer answer: I think some example code will be the most explanatory:

$a = new stdclass();
$b = $a;
$c = &$a;
$a->field = 'asdf';
echo '$b->field = ' . $b->field . "\n"; // $b->field = asdf
echo '$c->field = ' . $c->field . "\n"; // $c->field = asdf

So if you simply assign to fields of an object, there is no difference. The ampersand only makes a difference if you overwrite the variable itself.

$a = new stdclass();
$b = $a;
$c = &$a;
$a = 2;
echo 'is_object($b) = ' . is_object($b) . "\n"; // is_object($b) = 1
echo 'is_object($c) = ' . is_object($c) . "\n"; // is_object($c) = 0

But generally, that sort of behavior is bad juju (and only useful if you're trying to, say, return multiple values from a function; which you could also use list() for.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜