• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

[Perl]引用传递和值传递

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

这个题目似乎有些不太合适,因为这并不是我们常说的引用传递和值传递。但是我想提醒大家这一点,否则很容易犯错误。

问题:map语句的代码段中使用的 $_,是列表中的值本身,还是将列表中的值复制到 $_ 中?

例如,下面这段程序的运行结果是什么呢?

#!/usr/bin/perl
$,=',', $\="\n";
$a = [1,2,3];
print map { ++$_; } @$a;     # (A)
print @$a;                   # (B)

C程序员们通常会认为map会将@$a中的每个值复制到 $_ 中,加一后返回(这里我特地用了 ++$_ 使得它返回加一之后的值),因此(A)行输出 2,3,4 ,而(B)行输出 1,2,3 。实则不然。运行结果为

2,3,4
2,3,4

可见,并非@$a中的元素复制到$_中,而是$_本身就是@$a中的元素。而map的目的就是要改变操作数的值。下面这个例子可以很清楚地看到这一点。

map { ++$_ } (1,2,3);    # 运行时出错,++$_ 不能改变常量

类似地,grep的结果也是数组本身,返回值就是由操作数中的符合条件的元素本身组成的列表。如上例:

map { ++$_; } grep { $_ > 1 } @$a;  # 运行后 $a 为 [1,3,4]

如果实在不想让map改变操作数的值,可以将操作数转成引用之后再强制转成数组:

map { ++$_; } @{[ @$a ]};    # 运行后 $a 为 [1,2,3]

当然,上面例子中 ++ 操作符很明显会改变操作数的值,因此意识到上面的问题并不困难。不过如果是 s/// 运算符,可能就不那么明显了。

类似的情况还有函数调用时的 @_ ,它代表调用函数时的实际参数本身,而不是实际参数的拷贝。对@_进行修改,会直接影响到实参(就像C语言里面的传指针一样)。

一般我们在定义函数时都这么写:

sub foo {
my $arg1 = shift;
}

参数多时可能会这么写:

sub foo {
my ($arg1, $arg2, $arg3) = @_;
}

这样写之后,@_的值就被赋给了$arg1、$arg2等变量,以后对$arg1、$arg2的修改不会影响到实际参数。但如果想修改实际参数,就要这样做:

my $arg1 = \$_[0];
$$arg1 = 'Hello!';        # 调用函数时的第一个实参会变成 Hello!


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
perl示例1发布时间:2022-07-22
下一篇:
如何调试perl脚本发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap