0

例を考えてみましょう。

会社のスタッフを処理するアプリケーションライブラリ。スタッフの詳細は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::$employeesためStaff::$teamsStaff::$teams_names['Team Name']への参照になりStaff::$teams[n]ます。同様に、などStaff_Team::$managersへの参照の配列になります。 しかし、私が述べたように、参照を使い始めるとすぐに、メモリ使用量が増加します。Staff::$employees

質問:
では、これをどのように処理する必要がありますか?
参照渡しを使用してメモリ使用量を気にする必要はありませんか、それとも値渡しを使用する必要がありますか?
この場合、どちらが優れているのか、そしてその理由は何ですか?

注1:私は(私が思うに)オブジェクトを値で渡すことと参照で渡すことの違いを理解しています。この例では、どちらが優れているかを尋ねているだけです。
注2:作成後にStaff_Employeeオブジェクトが操作される場合があります。おそらく非常に最小限です。

4

1 に答える 1

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()ます)。

于 2011-03-07T01:23:24.327 に答える