7

In Dart, looking at the code below, does it 'pass by reference' for list and 'pass by value' for integers? If that's the case, what type of data will be passed by reference/value? If that isn't the case, what's the issue that causes such output?

void main() {
  var foo = ['a','b'];
  var bar = foo;
  bar.add('c');
  print(aoo); // [a, b, c]
  print(bar); // [a, b, c]
  
  var a = 3;
  int b = a;
  b += 2;
  print(a); // 3
  print(b); // 5
}
fendy3d
  • 363
  • 3
  • 9
  • You're not actually passing anything here. – Lasse V. Karlsen Jan 09 '21 at 14:08
  • When you copy the value of one variable to another, you copy the value of that variable, nothing else. When you copy an int, a primitive, you copy the value of the int, but when you copy a list, you copy *a reference* to the list. So now you have two references, but they refer to the same list. – Lasse V. Karlsen Jan 09 '21 at 14:18
  • 1
    Also see: [What is the true meaning of pass-by-reference in modern languages like Dart?](https://stackoverflow.com/questions/25170094/what-is-the-true-meaning-of-pass-by-reference-in-modern-languages-like-dart) – jamesdlin Jan 09 '21 at 20:47

3 Answers3

8

The question your asking can be answered by looking at the difference between a value and a reference type.

Dart like almost every other programming langue makes a distinction between the two. The reason for this is that you divide memory into the so called stack and the heap. The stack is fast but very limited so it cannot hold that much data. (By the way, if you have too much data stored in the stack you will get a Stack Overflow exception which is where the name of this site comes from ;) ). The heap on the other hand is slower but can hold nearly infinite data.

This is why you have value and reference types. The value types are all your primitive data types (in Dart all the data type that are written small like int, bool, double and so on). Their values are small enough to be stored directly in the stack. On the other hand you have all the other data types that may potentially be much bigger so they cannot be stored in the stack. This is why all the other so called reference types are basically stored in the heap and only an address or a reference is stored in the stack.

So when you are setting the reference type bar to foo you're essentially just copying the storage address from bar to foo. Therefore if you change the data stored under that reference it seems like your changing both values because both have the same reference. In contrast when you say b = a your not transferring the reference but the actual value instead so it is not effected if you make any changes to the original value.

I really hope I could help answering your question :)

Stefan
  • 352
  • 2
  • 17
2

In Dart, all type are reference types. All parameters are passed by value. The "value" of a reference type is its reference. (That's why it's possible to have two variables containing the "same object" - there is only one object, but both variables contain references to that object). You never ever make a copy of an object just by passing the reference around. Dart does not have "pass by reference" where you pass a variable as an argument (so the called function can change the value bound to the variable, like C#'s ref parameters).

Dart does not have primitive types, at all. However (big caveat), numbers are always (pretending to be) canonicalized, so there is only ever one 1 object in the program. You can't create a different 1 object. In a way it acts similarly to other languages' primitive types, but it isn't one. You can use int as a type argument to List<int>, unlike in Java where you need to do List<Integer>, you can ask about the identity of an int like identical(1, 2), and you can call methods on integers like 1.hashCode.

lrn
  • 64,680
  • 7
  • 105
  • 121
  • BTW, [`SendPort.send`](https://api.dart.dev/stable/dart-isolate/SendPort/send.html) does refer to "primitive values", although I'm not sure what else it should call them ("basic values"?). Maybe it shouldn't try to name/classify them at all. – jamesdlin Aug 16 '21 at 03:55
  • It should probably say "JSON-like" values (numbers, booleans, strings, null, and the lists of such and maps from string to such). I also sometimes call them "system types" or "system interaction types" because strings and integers are used to communicate with the rest of the world fairly directly (`print` prints a string, I/O operations expect and produce numbers, so you can't just show up with your own implementation and expect the underlying system to understand them). – lrn Aug 16 '21 at 07:41
2

If you want to clone or copy a list

var foo = ['a', 'b'];
var bar = [...foo];
bar.add('c'); 
print(bar);  // [a, b, c]
print(foo);  // [a, b]

var bar_two = []; //or init an empty list
bar_two.addAll([...bar]);
print(bar_two); // [a, b, c]

Reference link Clone a List, Map or Set in Dart

ClarkCluster
  • 446
  • 4
  • 7