1,& 援用(https://www.cnblogs.com/chrdai/p/11061174.html)
在 PHP 中,将变量 $a
赋值给 $b
,实际上就是将两个变量指向了同样的内存地址。
$a = range(1,100000);
var_dump(memory_get_usage()); // int(6698184)
$b = $a;
var_dump(memory_get_usage()); // int(6698184)
$a = range(1,200000);
var_dump(memory_get_usage()); // int(17184024)
从上边能够看到,当 $b=$a
时,并不是重新分配内存空间给 $b
,而是将两个变量指向了同样的内存地址。而当给 $a
从新赋值时,则是从新开拓一片内存空间给 $a
。
变量间的援用 赋值,就是将变量都指向同一个内存地址,当任意一个变量值发生变化时,就会将两个变量指向的内存地址都批改为新调配的内存地址。
$a = range(1,100000);
var_dump(memory_get_usage()); // int(6698208)
$b = &$a;
var_dump(memory_get_usage()); // int(6698208)
$a = range(1,100000);
var_dump(memory_get_usage()); // int(6698208)
对于援用的变量执行 unset
操作,也只会勾销援用,而不会销毁内存空间。
$a = 1;
$b = & $a;
unset($b);
echo $a;
对象的援用:
class A {
public $name = 1;
function getName(){echo $this->name;}
}
$a = new A;
$b = $a; // $b 与 $a 指向同一个内存空间地址
$b->name = 2;
$a->getName(); // 2
变量援用示例:
$d = ['a', 'b', 'c'];
foreach($d as $k => $v)
{$v = &$d[$k];
}
// 最终程序执行实现之后 $d 的值是?
第一次遍历:$d[0]
被援用赋值给 $v
,都指向了同一个值的内存地址 ‘a’。
第二次遍历:$d[1]
被援用赋值给 $v
,因为之前 $v
和 $d[0]
都指向了同一个地址,因而,这一次循环会将 $d[0]
和 $v
都被批改成了 $d[1]
的值 b。
第三次遍历:$d[2]
被援用赋值给 $v
,于之前 $v
和 $d[1]
都指向了同一个地址,因而,这一次循环会将 $d[1]
和 $v
都被批改成了 $d[2]
的值 c。
因而最终 $d = ['b', 'c', 'c']
函数援用
function t(&$a)
{$a++;}
$a = 1;
t($a);
echo $a; // 2
通过援用的模式传递给函数参数,必须是一个变量名,而不能是一个确定的值,否则会报错。
function &t()
{
static $a = 0;
$a++;
echo $a;
return $a;
}
$b = t(); // 输入:1
$b = 5;
$b = t(); // 输入:2
$b = &t(); // 输入 3。$b=3
$b = 5; // $a = 5
$b = t(); // 输入:6
通过 $b=t()
模式调用的函数,并不是援用调用函数,和一般函数调用一样。$b=&t()
这样的模式才是函数的援用调用。因为动态变量在函数完结后不会销毁的性质,因而,第一次调用函数时,会输入 1,第二次调用时,输入 2。第三次是援用调用函数,是将 return
后的变量 $a
的地址与 $b
的内存地址指向同一个地址。因而,在给 $b
赋值为 5 后,再次调用函数,就会输入 6。
// 官网示例:class talker{
private $data = 'Hi';
public function & get()
{return $this->data;}
public function out()
{echo $this->data;}
}
$a = new talker();
$b = &$a->get();
$a->out();
$b = 'How';
$a->out();
$b = 'are';
$a->out();
$b = 'you';
$a->out();
// 最终输入:HiHowareare
2,PHP 中的 COW (Copy-on-Write 写时复制) 机制
写时复制,即在变量进行写入时,才会复制一份内存,这是内存优化的罕用伎俩。
在通过变量赋值的形式赋值变量时,不会申请新的内存给新的变量,只是应用一个计数器来共用内存。只有当其中某一个变量的值发生变化时,才会调配新的内存给变量的变量。
罕用场景有:变量的屡次赋值;函数的参数传递,并在函数体内批改实参等。
3,动态变量
动态变量仅在部分函数作用域中存在,且仅在函数第一次执行时创立,当函数执行结束之后,动态变量的值不会失落。
function t(){
static $a = 1;
$a++;
echo $a;
}
t(); // 2
t(); // 3
t(); // 4
4,== 与 === 的区别
两者均用于判断等号前后的值是否相等,区别在于 ===
在判断值相等与否的同时,还会判断值的类型是否相等,仅当值与数据类型均雷同时,===
才会返回 true
,其余状况就返回 false
。而 ==
在值相等的状况下就会返回 true
,无论数据类型是否雷同。
$a = 0;
$b = '';
var_dump($a == $b); // boolean true
var_dump($a === $b); // boolean false
5,isset 和 empty 的区别 isset()
:变量存在且值不为 NULL
就返回 true
,反之返回 false
。empty()
:变量不存在或者变量值为 false
时就返回 true
,反之返回 false
。
$a = '';
$b = 0;
$c = false;
$d = 1;
$e = '0';
$f = '0.0';
$g = null;
var_dump(isset($m)); // boolean false
var_dump(isset($a)); // boolean true
var_dump(isset($b)); // boolean true
var_dump(isset($c)); // boolean true
var_dump(isset($d)); // boolean true
var_dump(isset($e)); // boolean true
var_dump(isset($f)); // boolean true
var_dump(isset($g)); // boolean false
var_dump(empty($m)); // boolean true
var_dump(empty($a)); // boolean true
var_dump(empty($b)); // boolean true
var_dump(empty($c)); // boolean true
var_dump(empty($d)); // boolean false
var_dump(empty($e)); // boolean true
var_dump(empty($f)); // boolean false
var_dump(empty($g)); // boolean true
6,魔术函数(魔术办法) 魔术办法都必须被申明为public
- __construct():该办法在对象被实例化时会主动调用。
- __destruct():当对象的所有援用被删除或者当对象被事实销毁时执行。
class A {function __construct()
{echo '我被主动执行了!';}
}
$a = new A;
class B {
public $name;
public function __construct($name){
$this->name = $name;
echo '你的名字是:'.$this->name;
}
public function __destruct(){echo '对象被销毁了';}
}
$b = new B('Jeccy');
- __call($name, $arguments):在对象中调用一个不可拜访(办法不存在或被定义为
protected
、private
)的办法时,会被调用。$name
为不可拜访的办法名,$arguments
为拜访时传的参数。
class B {
public $name=22;
protected function getName()
{echo $this->name;}
function __call($name, $arguments){var_dump($name);
var_dump($arguments);
}
}
$b = new B;
$b->getName(1,2); // string 'getName' Array ([0] => 1 [1] => 2 )
$b->getAge(3,4); // string 'getAge' Array ([0] => 3 [1] => 4 )
- callStatic($name, $arguments):在动态上下文中拜访一个不可拜访(办法不存在或被定义为
protected
、private
)的办法时,会被调用。$name
为不可拜访的办法名,$arguments
为拜访时传的参数。
class B {public static function __callStatic($name, $arguments)
{
echo $name.'<br>';
var_dump($arguments);
}
}
$b = new B;
B::getAge('static method');// getAge Array ([0] => static method )
- __get($name):服务不可拜访(不存在或设置为非
public
)属性时,会被调用。$name
为拜访的属性的名称。
class B {
private $name = 'jeccy';
public $age = 2;
protected $sex = 1;
public function __get($name)
{echo '属性'.$name.'不存在或不可被拜访 <br>';}
}
$b = new B;
echo $b->name; // 属性 name 不存在或不可被拜访
echo $b->age; // 2
echo $b->sex; // 属性 sex 不存在或不可被拜访
echo $b->address; // 属性 address 不存在或不可被拜访
- __set(string $name, mixed $value):在给不可拜访的属性赋值时,会被调用。
$name
为不可拜访的属性的名称;$value
为给属性赋的值。
class B {
private $name = 'jeccy';
public $age = 2;
protected $sex = 1;
public function __set($name, $value)
{$this->$name = $value;}
public function getInfo()
{
echo 'name='.$this->name.',';
echo 'age='.$this->age.',';
echo 'sex='.$this->sex;
echo 'sex='.$this->sex;
}
}
$b = new B;
$b->name = 'mark';
$b->age = 3;
$b->sex = 2;
$b->address = 2;
$b->getInfo(); // name=mark,age=3,sex=2,address=2
*__isset(string $name):当被不可拜访属性调用 isset()
或 empty()
时,此办法会被调用。$name
为拜访的属性名。
class B {
private $name = 'jeccy';
public $age = 2;
protected $sex = 1;
public function __isset($name)
{echo isset($this->$name) ? $name.'存在 <br>' : $name.'不存在 <br>';
}
public function getInfo()
{
echo 'name='.$this->name.',';
echo 'age='.$this->age.',';
echo 'sex='.$this->sex;
}
}
$b = new B;
isset($b->name); // name 属性存在
isset($b->age); // age 属性能够拜访,故不会调用 __isset() 办法
isset($b->sex); // sex 属性存在
isset($b->address); // address 属性不存在
- _unset(string $name):当对不可拜访属性调用
unset()
时,会被调用。参数$name
是指要拜访的变量名称。
class B {
private $name = 'jeccy';
public $age = 2;
protected $sex = 1;
public function __unset($name)
{unset($this->$name);
}
public function getInfo()
{var_dump($this);
}
}
$b = new B;
unset($b->name); // name 存在
unset($b->age); // age 属性能够拜访,故不会调用 __isset() 办法
unset($b->sex); // sex 存在
unset($b->address); // address 不存在
$b->getInfo(); // D:wamp64wwwmineaa.php:14: object(_B_)[_1_]
7,动态属性和静态方法(参考:https://www.cnblogs.com/chrdai/p/6863090.html)