多数大学生出来选择的工作和专业无关
首页 > 专业知识

PHP中引用&的使用注意事项

时间:2018-05-02 18:23:10 [来源]:郑州PHP培训学校

   PHP中引用&的使用注意事项

  之前一个朋友的帖子提到过这方面的疑问,这里简单整理一下,希望能让更多新学php的朋友得到帮助。
  php的引用(就是在变量或者函数、对象等前面加上&符号)是个高级话题,新手多注意,正确的理解php的引用很重要,对性能有较大影响,而且理解错误可能导致程序错误!
  很多人误解php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别。C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,php中引用采用的是“写时拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的,比如下面的代码:
  $a = array('a','c'...'n');
  $b = $a;
  如果程序仅执行到这里,$b和$b是相同的,但是并没有像C那样,$a和$b占用不同的内存空间,而是指向了同一块内存,这就是php和c的差别,并不需要写成$b=&$a才表示$b指向$a的内存,zend就已经帮你实现了引用,并且zend会非常智能的帮你去判断什么时候该这样处理,什么时候不该这样处理。
  如果在后面继续写如下代码,增加一个函数,通过引用的方式传递参数,并打印输出数组大小。
  function printArray(&$arr) //引用传递
  {
  print(count($arr));
  }
  printArray($a);
  上面的代码中,我们通过引用把$a数组传入printArray()函数,zend引擎会认为printArray()可能会导致对$a的改变,此时就会自动为$b生产一个$a的数据拷贝,重新申请一块内存进行存储。这就是前面提到的“写时拷贝”概念。
  如果我们把上面的代码改成下面这样:
  function printArray($arr) //值传递
  {
  print(count($arr));
  }
  printArray($a);
  上面的代码直接传递$a值到printArray()中,此时并不存在引用传递,所以没有出现写时拷贝。
  大家可以测试一下上面两行代码的执行效率,比如外面加入一个循环1000次,看看运行的耗时,结果会让你知道不正确使用引用会导致性能下降30%以上。
  php代码优化及php相关问题总结
  1,在函数中,传递数组时使用 return 比使用 global 要高效,比如:
  function userloginfo($usertemp){
  $detail=explode("|",$usertemp);
  return $detail;
  }
  $login=userloginfo($userdb);
  比
  function userloginfo($usertemp){
  global $detail;
  $detail=explode("|",$usertemp);
  }
  userloginfo($userdb);
  要高效
  2,(这个代码用于得到程序目录对应的网址,推荐使用)$urlarray=explode('/',$HTTP_SERVER_VARS['REQUEST_URI']);$urlcount=count($urlarray);unset($urlarray[$urlcount-1]);$ofstarurl='http://'.$HTTP_SERVER_VARS['HTTP_HOST'].implode('/',$urlarray);这段代码比
  $pre_urlarray=explode('/',$HTTP_SERVER_VARS['HTTP_REFERER']);$pre_url=array_pop($pre_urlarray);
  要高效
  3,在循环中判断时,数值判断使用恒等要比等于高效$a=2;$b=2;
  比如
  if($a==$b)$c=$a;
  比
  if($a===$b)$c=$a;
  高效
  4,mysql 查询时尽量使用where in 少用 limitlimit查多记录的前几条, 速度很快, 但是查询最面几条就会慢使用in .在查询连续性记录,非常快, 非连续性记录第一次运行会稍微慢一点,但是之后将比较快!
  5,NT服务器数据操作稳定性不及unix/linux
  6,输出前使用尽量使用 ob_start(); 可以加快输出速度,适用NT或nuli/linux,对unlix类服务器 如果使用 ob_start('ob_gzhandler');输出效率将更高7,判断的时候尽量使用if($a==他的值) 否定的时候尽量使用if(empty($a)),因为这样程序运行更快速8,使用不等时 != 与 <> 效率相当
  9,个人经验得 使用 $a="11111111111111"; 的效率和 $a='11111111111111'; 相当.并不象书本说的相差很大10,使用规范的SQL语句, 会有利于MySQL的解析11,使用
  if($online){
  $online1=$online;
  setcookie('online1',$online,$cookietime,$ckpath,$ckdomain,$secure);}
  COOKIE将马上生效
  使用
  if($online)
  setcookie('online1',$online,$cookietime,$ckpath,$ckdomain,$secure);COOKIE需要再刷新一次才能生效
  12,使用
  $handle=fopen($filename,wb);
  flock($handle,LOCK_SH);
  $filedata=fread($handle,filesize($filename));fclose($handle);
  比
  file($filename);
  无论在速度还是稳定上都要优秀
  用PHP读取文件的正确方法
  了解如何使用 PHP 的各种文件函数。查看诸如 fopen、fclose 和 feof 之类的基本文件函数;了解诸如 fgets、fgetss 和 fscanf 之类的读取函数。并且发现用一两行代码处理整个文件的函数。
  让我们算一算有多少种方法
  处理诸如 PHP 之类的现代编程语言的乐趣之一就是有大量的选项可用。PHP 可以轻松地赢得 Perl 的座右铭“There's more than one way to do it”(并非只有一种方法可做这件事),尤其是在文件处理上。但是在这么多可用的选项中,哪一种是完成作业的最佳工具?当然,实际答案取决于解析文件的目标,因此值得花时间探究所有选项。
  传统的 fopen 方法
  fopen 方法可能是以前的 C 和 C++ 程序员最熟悉的,因为如果您使用过这些语言,那么它们或多或少都是您已掌握多年的工具。对于这些方法中的任何一种,通过使用 fopen(用于读取数据的函数)的标准方法打开文件,然后使用 fclose 关闭文件,如清单 1 所示。
  清单 1. 用 fgets 打开并读取文件
  $file_handle = fopen("myfile", "r");
  while (!feof($file_handle)) {
  $line = fgets($file_handle);
  echo $line;
  }
  fclose($file_handle);
  虽然大多数具有多年编程经验的程序员都熟悉这些函数,但是让我对这些函数进行分解。有效地执行以下步骤:
  打开文件。$file_handle 存储了一个对文件本身的引用。
  检查您是否已到达文件的末尾。
  继续读取文件,直至到达文件末尾,边读取边打印每行。
  关闭文件。
  记住这些步骤,我将回顾在这里使用的每个文件函数。
  fopen
  fopen 函数将创建与文件的连接。我之所以说“创建连接”,是因为除了打开文件之外,fopen 还可以打开一个 URL:
  $fh = fopen("http://127.0.0.1/", "r");
  这行代码将创建一个与以上页面的连接,并允许您开始像读取一个本地文件一样读取它。
  注: fopen 中使用的 "r" 将指示文件以只读方式打开。由于将数据写入文件不在本文的讨论范围内,因此我将不列出所有其他选项。但是,如果是从二进制文件读取以获得跨平台兼容性,则应当将 "r" 更改为 "rb"。稍后您将看到这样的示例。
  feof
  feof 命令将检测您是否已经读到文件的末尾并返回 True 或 False。清单 1 中的循环将继续执行,直至您达到文件“myfile”的末尾。注:如果读取的是 URL 并且套接字由于不再有任何数据可以读取而超时,则 feof 也将返回 False。
  fclose
  向前跳至清单 1 的末尾,fclose 将实现与 fopen 相反的功能:它将关闭指向文件或 URL 的连接。执行此函数后,您将不再能够从文件或套接字中读取任何信息。
  fgets
  在清单 1 中回跳几行,您就到达了文件处理的核心:实际读取文件。fgets 函数是处理第一个示例的首选武器。它将从文件中提取一行数据并将其作为字符串返回。在那之后,您可以打印或者以别的方式处理数据。清单 1 中的示例将精细地打印整个文件。
  如果决定限制处理数据块的大小,您可以将一个参数添加到 fgets 中限制最大行长度。例如,使用以下代码将行长度限制为 80 个字符:
  $string = fgets($file_handle, 81);
  回想 C 中的“\0”字符串末尾终止符,将长度设为比实际所需值大一的数字。因而,如果需要 80 个字符,则以上示例使用 81。应养成以下习惯:只要对此函数使用行限制,就添加该额外字符。
  fread
  fgets 函数是多个文件读取函数中惟一一个可用的。它是一个更常用的函数,因为逐行解析通常会有意义。事实上,几个其他函数也可以提供类似功能。但是,您并非总是需要逐行解析。
  这时就需要使用 fread。fread 函数与 fgets 的处理目标略有不同:它趋于从二进制文件(即,并非主要包含人类可阅读的文本的文件)中读取信息。由于“行”的概念与二进制文件无关(逻辑数据结构通常都不是由新行终止),因此您必须指定需要读入的字节数。
  $fh = fopen("myfile", "rb");
  $data = fread($file_handle, 4096); 使用二进制数据注意:此函数的示例已经使用了略微不同于 fopen 的参数。当处理二进制数据时,始终要记得将 b 选项包含在 fopen 中。如果跳过这一点,Microsoft? Windows? 系统可能无法正确处理文件,因为它们将以不同的方式处理新行。如果处理的是 Linux? 系统(或其他某个 UNIX? 变种),则这可能看似没什么关系。但即使不是针对 Windows 开发的,这样做也将获得良好的跨平台可维护性,并且也是应当遵循的一个好习惯。
 

上一篇:在PHP内创建一个Atom提要

下一篇:PHP伪静态化页面的实现