php的引用操作符&

本文详细解析PHP中的引用操作符&的功能与应用场景,通过示例对比普通赋值与引用赋值的区别,并讨论其在数据库连接及对象创建中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

php的引用操作符&

2010年2月21日

说实在话在一年前战地写PHP代码的时候从来没有想过什么系统资源什么的,幸好PHP对于内存等其它的系统资源回收还是相当积极的。但是不管怎么样还是要注意的,毕竟资源是是宝贵的嘛。

那么我们开始今天的话题吧,说说PHP的引用操作符&,熟悉C的都知道C中有一个被称为指针的东西,指针就是指向内存地址的。这个&也是具有同样的功能的。

看如下代码:

$source="110"; $a=$source; $b=&$source; $source="120"; echo $a."\r\n",$b;

这段代码运行之后你会发现一个问题,$a的值并没有根据第四行代码$source的值改变而变化依然是原来的赋值“110”,这个很好理解,$a赋值的时候$source的值就是110,她只是把$source的值copy一个给了自己。

显然你也会注意到变量$b的值发生了变化,$a和变量$b几乎是同时的赋值,为什么出现了如此巨大的差异呢——一个管打人的一个管救人的,差异够大哦!

这就是PHP的引用操作符&的问题了,变量$b因为在赋值的时候应用到了&导致,$b不是copy“110”给自己而是,直接指向了$source的老巢,以后$source就是他$b了。$source 不管怎么变化都会导致$b的变化——很像是一个主机连接两个显示器的关系,既然是这样的关系了$b的变化当然会导致$source的变化了

看:

$b=122; echo $source;

输出的结果:122,知道了吧这两个变量从此就是一个“人”了,不要欺负他们哦!

其实为了程序的可读性和随后的编程的误操作,我是不推荐使用这个&引用操作符的,你想啊。你在10000行前,使用了一个$b=&$source;到10000行之后你就不一定记得了,万一你不小心赋错了值,排错的时候就够你喝一壶了!呵呵……

其实这个操作符更多的是用在了数据库连接上,因为我们创建数据库连接对象的时候,往往只需要一个,太多了没用啊。

假设我们有一个类:

class MysqlConnect{} //用来创建数据库连接,那么我们每次调用的时候可以这样写 $conn=& new MysqlConnect();

这样的写法可以保证数据库的连接不会被重复的创建,耗费系统资源。但是如果你真的需要多个不同的连接,你千万不要这样写哦。

当然创建对象的时候这个PHP引用操作符确实是有用的,如果你一个PHP脚本程序上创建了上千个对象的话,系统的开销确实是很大的。如果没有必要创建多个的,尽量使用&吧!


from:http://www.phpiask.com/?p=412

<think>好的,我现在需要帮助用户了解PHP中的对象操作符的使用方法和功能。用户之前询问了关于`clone`关键字克隆属性的问题,现在转向对象操作符,特别是`->`和`::`。根据用户提供的引用,特别是引用2和3,他们提到了范围解析操作符`::`的用法,包括访问父类方法和类常量。同时,用户可能还想了解`->`操作符的使用,比如访问对象属性和方法。 首先,我需要确认用户的需求。他们可能希望得到关于这两个操作符的详细指南,包括它们的区别、使用场景以及示例。用户提供的引用中提到`::`用于访问静态成员、常量和父类方法,而`->`用于访问实例属性和方法。此外,用户之前的问题涉及对象克隆,可能对对象实例的操作符更感兴趣,但也不能忽略静态上下文的使用。 接下来,我需要整理这两个操作符的用法。对于`->`,需要说明它用于实例,如访问属性、调用方法,以及链式调用。对于`::`,需要覆盖访问静态成员、类常量、父类方法,以及延迟静态绑定。还要注意它们的使用限制,比如`::`不能用于实例化的对象,而`->`不能用于静态属性或方法。 然后,结合用户提供的引用引用3中提到了在子类中使用`parent::`调用父类构造函数,以及使用`self::`访问当前类的常量。这可以作为示例的一部分。引用2提到在子类中访问被重写的父类方法,所以需要强调`parent::`的使用场景。 另外,用户可能对操作符的优先级和注意事项感兴趣,比如使用`{}`包裹复杂表达式,或者在动态调用方法时的处理。还需要提到PHP 8的新特性,比如`::class`对对象实例的支持,以保持回答的更新。 最后,要确保回答结构清晰,分点说明,每个部分都有代码示例,帮助用户理解。同时,生成的相关问题需要覆盖常见疑问,比如动态属性调用、`self`和`parent`的区别、静态与实例访问的差异等。</think>#### PHP对象操作符深度解析指南 PHP的对象操作符`->`与范围解析操作符`::`是面向对象编程的核心工具,二者在内存访问机制和使用场景上有本质区别。以下是详细的对比分析: --- ### 一、对象操作符`->`(实例级操作) **使用场景:** 操作对象实例的属性和方法 #### 1. 基础用法示例 ```php class User { public $name = 'John'; public function login() { return "{$this->name} logged in"; } } $user = new User(); echo $user->name; // 访问属性 → 输出John echo $user->login(); // 调用方法 → 输出John logged in ``` #### 2. 链式调用特性 ```php class QueryBuilder { public function select($fields) { /* ... */ return $this; } public function where($condition) { /* ... */ return $this; } } $qb = new QueryBuilder(); $qb->select('*')->where('id=1'); // 链式操作[^1] ``` #### 3. 动态属性访问 ```php $property = 'email'; echo $user->$property; // 等效于$user->email ``` --- ### 二、范围解析操作符`::`(类级操作) **使用场景:** 访问静态成员、类常量、父类方法 #### 1. 静态成员访问 ```php class Config { const VERSION = '1.0'; public static $env = 'prod'; public static function getEnv() { return self::$env; } } echo Config::VERSION; // 访问常量 → 1.0 echo Config::$env; // 访问静态属性 → prod echo Config::getEnv(); // 调用静态方法 → prod ``` #### 2. 父类方法调用 ```php class ParentClass { protected static function baseMethod() { return "Parent method"; } } class ChildClass extends ParentClass { public static function show() { return parent::baseMethod(); // 调用被覆盖的父类方法[^2] } } echo ChildClass::show(); // 输出Parent method ``` #### 3. 延迟静态绑定 ```php class A { public static function create() { return new static(); // 根据调用类动态绑定 } } class B extends A {} $obj = B::create(); echo get_class($obj); // 输出B(而非A)[^3] ``` --- ### 三、核心差异对照表 | **特性** | `->` 操作符 | `::` 操作符 | |------------------------|--------------------------------|---------------------------------| | **操作对象** | 实例对象 | 类名/`parent`/`self`/`static` | | **可访问内容** | 非静态属性/方法 | 静态属性/方法/常量/父类元素 | | **内存位置** | 操作堆内存中的对象实例 | 直接访问类结构内存区 | | **动态调用支持** | 支持变量属性名(`$obj->$var`) | 支持变量类名(`$class::CONST`) | | **继承关系影响** | 受实例化类影响 | 受当前作用域类影响 | --- ### 四、高级应用场景 #### 1. 回调函数中的对象操作 ```php $callback = function() use ($user) { return $user->getName(); }; ``` #### 2. 特性(Trait)方法调用 ```php trait Loggable { public function log($msg) { echo "[LOG] $msg"; } } class Order { use Loggable; } (new Order())->log("Created"); // 使用->调用Trait方法 ``` #### 3. 对象属性遍历 ```php foreach ($user as $key => $value) { echo "$key: $value"; // 需要类实现Iterator接口 } ``` --- ### 五、PHP8新特性支持 #### 1. `::class`增强 ```php $obj = new User(); echo $obj::class; // 直接获取对象类名 → User(PHP8+特性) ``` #### 2. Nullsafe操作符`?->` ```php // 传统写法 if ($user !== null) { $name = $user->getName(); } // PHP8+写法 $name = $user?->getName(); // 自动处理null值 ``` --- ### 六、常见错误排查 1. **非静态方法静态调用** ```php class Test { public function show() {} } Test::show(); // 严格模式下抛出Warning ``` 2. **静态属性实例访问** ```php echo (new Test())::$staticVar; // 语法错误 ``` 3. **作用域解析优先级** ```php class Demo { const TYPE = 'A'; } $type = 'TYPE'; echo Demo::$type; // 错误!应使用常量访问符: Demo::TYPE ``` --- ### 相关问题 1. 如何动态选择要调用的对象方法? 2. `self::`和`static::`在继承中有何区别? 3. PHP中能否通过`::`访问实例属性?为什么? --- ### 附录:引用说明 [^1]: 链式方法调用在Builder模式中的典型应用 [^2]: 使用`parent::`突破子类方法覆盖的限制 [^3]: 延迟静态绑定实现多态性的核心机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值