(如何)我应该使用对象引用?

时间:2011-03-06 11:51:42

标签: php performance object pass-by-reference pass-by-value

考虑一个例子:

处理公司员工的应用程序库。员工详细信息存储在CSV文件中(请不要对此进行评判,因为这仅用作示例) 处理员工信息的类是(代码非常简单,只是为了给你提供图片):

class Staff {
    /* 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;
}

现在,目前应用程序中没有使用任何引用。所有对象变量都是按值传递的。我认为这可能会有一些开销。因此,一旦创建了所有Employee和Team对象,我就会尝试将所有调用更改为引用,例如:

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

但这暂时增加了内存使用量,这对我来说是令人惊讶的。我使用的示例只有200名员工,但我可以想象,当必须与企业打交道时,这可能会达到数千甚至更多,内存使用量会增长得更多。

当我想到这个例子时,我试图模仿ORM,我可以做这样的事情:

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

理想情况下,“正确的”(初始?)对象只会存储在Staff::$employeesStaff::$teams中,因此Staff::$teams_names['Team Name']会引用Staff::$teams[n]。同样地,Staff_Team::$managers将是对Staff::$employees等的引用数组 但正如我所提到的 - 一旦我开始使用引用,内存使用率就会上升。

问题(S):
那我该怎么处理呢? 我应该使用pass-by-reference而不用担心内存使用,还是应该使用pass-by-value?
在这种情况下哪一个更好?为什么?

注1:我(我想)确实理解了按值和引用传递对象之间的区别。我只是问这个例子中哪一个更好。
注2:创建后,Staff_Employee对象可能会有一些操作。虽然可能很小。

1 个答案:

答案 0 :(得分:1)

简短回答:不要使用&符号,“按值传递”(这容易引起混淆,在其他语言中称为传递引用。)

更长的答案:我认为一些示例代码将是最具说明性的:

$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

因此,如果您只是分配给对象的字段,则没有区别。如果你覆盖变量本身,那么&符只会产生影响。

$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

但一般来说,这种行为是糟糕的juju(只有当你试图从函数中返回多个值时才有用;你也可以使用list()。)