java和cpp的forEach循环的区别
众所周知,java内的函数传参方法只有一种—==值传递==,cpp分为值传递和地址传递
那么两者的forEach循环有什么区别呢?
java中的forEach与函数传参类似
-
对于基本数据类型(八大基本数据类型), forEach循环并不会改变他们实际的数值
- byte:字节类型,Java中最小的数据类型,1个字节,占8位,取值范围-128127,默认值0
- char:字符型,用于存储单个字符,2个字节,占16位,取值范围0~65535,默认值为空
- short:短整型,2个字节,占16位,取值范围-3276832717,默认值0
- int:整型,用于存储整数,4个字节,占32位,取值范围-2147483648~2147483647,默认值0
- long:长整型,8个字节 占64位,-263~263-1,默认值0L
- float:浮点型,占32位,即4个字节,用于存储带小数点的数字(与double的区别在于float类型有效小数点只有6~7位),默认值0
- double:双精度浮点型,用于存储带有小数点的数字,8个字节 占64位,默认值0
- boolean:布尔类型,1个字节 占8位,用于判断真或假(仅有两个值,即true、false),默认值false
-
对于引用数据类型
引用数据类型在被创建时,首先要在栈上给其引用(句柄)分配一块内存,而对象的具体信息都存储在堆内存上,
forEach内对于调出来的元素的操作==会改变==引用类型的实际的值
==警告==: 有些人认为包装器类可以用来实现修改数值参数的方法, 然而这是错误的。在第4 章中曾经讲到, 由于Java 方法都是值传递, 所以不可能写一个下面这样的能够增加整型参数值的Java 方法。
问题是==Integer 对象是不可变的==: 包含在包装器中的内容不会改变: 不能使用这些包装器类创建修改数值参数的方法。
如果想编写一个修改数值参数值的方法, 就需要使用在org.omg.CORBA
包中定义的
持有者( holder ) 类型, 包括IntHolder、BooleanHolder
等。每个持有者类型都包含一个公有(!)域值, 通过它可以访问存储在其中的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void triple(int x) { x=3*x; }
public static void triple(Intger x) { x=3*x; }
public static void triple(IntHolder x) { x.value=3*x.value; }
|
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| import java.util.ArrayList; import java.util.Date; import java.util.List;
public class Test { public static void main(String[] args) { Book[] books =new Book[]{new Book(12),new Book(122),new Book(1122),new Book(812),new Book(612)}; List<CartItem> cartItemList = new ArrayList<>(5); cartItemList.add(new CartItem(books[0])); cartItemList.add(new CartItem(books[1])); cartItemList.add(new CartItem(books[2])); cartItemList.add(new CartItem(books[3])); cartItemList.add(new CartItem(books[4])); for(CartItem e :cartItemList) { e.setBook(new Book(e.getBook().price+10000)); } cartItemList.forEach(System.out::println); Integer x=10; List<Integer> integerList =List.of(1,2,3,4,5); for(Integer e: integerList) { e= new Integer(e.intValue()+1); } integerList.forEach(System.out::println); x=11; System.out.println(x); } } class CartItem { Book book; Date date=new Date(); public void setBook(Book book) { this.book = book; }
@Override public String toString() { return "CartItem{" + "book=" + book.price + '}'; }
public CartItem(Book book) { this.book = book; }
public Book getBook() { return book; } } class Book { Book(int price) { this.price = price; } public Integer price; }
|
debug
-
通过debug发现,cartItem和integer的地址都是相应的List的元素的地址
🎈说明对于引用类型,forEach采用的是地址传递
而变量Integer x
的地址在经过x=11
赋值之后,值改变,地址也改变,与Integer对象是不可变的相照应
cpp
- cpp中的forEach循环==不会==影响原本的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <bits/stdc++.h> class Integer{ public: int num; Integer(int num){ this->num = num; } Integer() {} }; int main() { string str = "abcdefg"; for (char ch : str) ch += 1; for (char ch : str) std::cout << ch << ' '; std::cout << '\n'; Integer integers[] = {Integer(4), Integer(5), Integer(6)}; for (Integer e : integers) e.num++; for (Integer e : integers) cout << e.num << ' '; getchar(); }
|