0

我有两个代码片段,它们做同样的事情,但是通过不同的方法,哪个更好,为什么?非常感谢。第一个处理函数 handle() 中的 $arr 并且不返回值,因为它是通过-通过引用,所有更改都发生在函数句柄()内,因此它不需要返回任何值。

第二个片段从函数 handle() 返回值并覆盖 $arr[]; 中的先前值;

一个不返回,另一个返回,我想知道哪种方法合适或可取,最重要的是,为什么,谢谢!返回和不返回之间的选择

第二个代码是

片段一:

class a {
    public function org(){
        $arr = array(1=>1,2=>2,3=>3);
        foreach($arr as $k=>&$v){
            $this->handle($v);
        }
        print_r($arr);
    }
    public function handle(&$item){
        $item+=1;
    }

}
$b = new a();
$b->org();

片段 B:

class a {
    public function org(){
    $arr = array(1=>1,2=>2,3=>3);
    foreach($arr as $k=>$v){
        $arr[$k] = $this->handle($v);
    }
    print_r($arr);
}
public function handle($item){
    return $item+=1;
}

}
$b = new a();
$b->org();
4

5 回答 5

1

一般来说

通过引用接受其参数并就地修改它们的函数(mutators)通常(但并非总是如此!)更有效。这是因为它们不需要消耗内存和 CPU 周期来复制它们的参数——它们将自己对参数进行操作。

处理其参数并返回结果值而不修改原始值(转换器)的函数使用起来更加灵活和方便。

公平地说,我还应该提到,如果一个函数希望能够报告可能的故障,那么这对转换器来说更难做到,因为它们已经返回了一个结果(另一方面,mutators 可以自由使用返回值以此目的)。然而,这种错误检查方式在今天已不受欢迎,通常不推荐使用。

例子

作为一个说明性示例,让我们比较一下函数shufflearray_unique. 它们都对数组进行操作,但第一个是mutator,第二个是transformer。假设我们要计算通过每个数组传递的结果:

$count = count(array_unique($array)); // convenient one-liner

shuffle($array);
$count = count($array); // two statements necessary: shuffle cannot be chained

该示例是人为设计的,但是如果array_unique并且shuffle是同一函数的不同实现,显然您更愿意array_unique在源代码中使用。

现在让我们通过比较 mutator 和 Transformer 版本的资源使用情况来看看 mutator 如何比转换器更有效sort

突变体:

$array = range(1, 10000);
shuffle($array);

sort($array);
$oneToTen = array_slice($array, 0, 10);
echo memory_get_peak_usage();

看到它在行动

变压器:

function transformer_sort($array)
{
    sort($array);
    return $array;
}

$array = range(1, 10000);
shuffle($array);

$oneToTen = array_slice(transformer_sort($array), 0, 10);
echo memory_get_peak_usage();

看到它在行动

如您所见,mutator 版本总共需要更少的内存来达到相同的结果。但是有一个权衡:代码不太方便,它“破坏”了我们的初始数据数组。如果我们需要保留初始数据,那么内存使用量将是相同的,消除了 mutator 的优势并留下了它的劣势。

结论

我建议遵循这个经验法则:

编写函数时,始终将其作为转换器而不是突变器作为首选。

如果您有性能问题,并且可以通过分析应用程序来证明这些问题可以通过使用 mutators 而不是转换器来解决,请将这些转换器替换为等效的 mutators。

于 2013-06-22T16:44:59.613 回答
0

最好的是:):

$arr[$k] = $v + 1;

否则-我假设您的代码只是一个示例-我建议使用函数(SnippetB)的返回值而不是通过引用传递。这就是返回值的用途,如果示例不是那么简单,通过引用传递可能会产生意想不到的副作用。

于 2013-06-22T16:42:07.533 回答
0

最简单的就是hek2mgl所说的。但是如果你只是想知道为什么,那是因为你创建另一个函数不仅会增加你正在使用的内存中的堆堆栈,而且需要额外的 CPU 步骤来调用该函数。

此外,对于返回值的函数,PHP 必须创建一个临时变量来保存和返回值。因此,您实际上是在临时复制内存中的数据。

但老实说,除非您的移动数组长度超过数百万,否则您不会看到太大的差异。我想说这两个功能在占用空间方面几乎相同。

于 2013-06-22T16:45:15.407 回答
0

要考虑的第三个选项,请记住数组永远不会离开类:

class a {
    private $arr;

    public function __construct() {
        $this->arr = array(1=>1,2=>2,3=>3);
    }

    public function org() {
        $this->handle();
        print_r($this->arr);
    }

    public function handle() {
        foreach(array_keys($this->arr) as $k){
            $this->arr[$k]++;
        }
    }
}

如果数组是类的属性,则不需要按值或引用传递。

于 2013-06-22T16:48:37.320 回答
0

避免像您一样通过引用传递,避免使用 &,这被认为是一种不好的做法。您可以只返回第二个示例代码中的值。

为什么?因为如果你有很多引用,更改另一个将很难跟踪发生了什么。

请记住,尽管默认情况下对象总是通过引用传递。

于 2013-06-22T16:49:44.147 回答