在 java 中,存在 “实” 和 “名” 的概念

在其他语言中,有的语言(例如 java、C#)直接取消了指针的相关语法,但由此就必须引入 “值类型” 和 “引用类型” 的概念。例如在 java 中,存在 “实” 和 “名” 的概念:

public static void Demo() {
  int[] arr = new int[10];
  int[] arr2 = arr; // “名”的复制,浅复制
  int[] arr3 = Arrays.copyOf(arr, arr.length); // 用库方法进行深复制
}

本质上来说,这个 “名” 就是栈空间上的一个指针,而 “实” 则是堆空间中的实际数据。如果取消指针概念的话,就要强行区分哪些类型是 “值类型”,会完全复制,哪些是 “引用类型”,只会浅复制。

C# 中的结构体和类的概念恰好如此,结构体是值类型,整体复制,而类是引用类型,要用库函数来复制。

而还有一些语言保留了指针的概念(例如 Go、Swift),但仅仅用于明确指向和引用的含义,并不提供指针偏移运算,来防止出现越界问题。例如 go 中:

func Demo() {
  var a int
  var p *int
  p = &a // OK
  r1 := *p // 直接解指针是OK的
  r2 := *(p + 1) // ERR,指针不可以偏移
}

swift 中虽然仍然支持指针,但非常弱化了它的概念,从语法本身就能看出,不到迫不得已并不推荐使用:

func f1(_ ptr: UnsafeMutablePointer<Int>) {
  ptr.pointee += 1 // 给指针所指向的值加1
}

func demo() {
  var a: Int = 5
  f1(&a)
}

OC 中的指针更加特殊和 “奇葩”,首先,OC 完全保留了 C 中的指针用法,而额外扩展的 “类” 类型则不允许出现在栈中,也就是说,所有对象都强制放在堆中,栈上只保留指针对其引用。虽然 OC 中的指针仍然是 C 指针,但由于操作对象的 “奇葩” 语法,倒是并不需要太担心指针偏移的问题

void demo() {
  NSObject *obj = [[NSObject alloc] init];
  // 例如调用obj的description方法
  NSString *desc = [obj description];
  // 指针仍可偏移,但几乎不会有人这样来写:
  [(obj+1) description]; // 也会越界
}

(六)隐式类型转换

隐式类型转换在一些场景下会让程序更加简洁,降低代码编写难度。比如说下面这些场景:

double a = 5; // int->double
int b = a * a; // double->int
int c = '5' - '0'; // char->int

但是有的时候隐式类型转化却会引发很奇怪的问题,比如说:

#define ARR_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
void f1() {
  int arr[5];
  size_t size = ARR_SIZE(arr); // OK
}
void f2(int arr[]) {
  size_t size = ARR_SIZE(arr); // WRONG
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值