【问题标题】:Is Dart pass by reference? [duplicate]Dart 是通过引用传递的吗? [复制]
【发布时间】:2019-11-21 01:54:07
【问题描述】:

在这篇文章中:Flutter video_player dispose

我询问了如何处理某些东西以便我可以再次使用它。提供的答案可以正常工作,但它给我留下了这个问题:

为什么这段代码能按预期工作?例如,它使用oldController 处理来自videoController 的旧实例

final oldController = videoController;

  WidgetsBinding.instance.addPostFrameCallback((_) async {
    await oldController.dispose();

    _initController(link); //contains reassignment of videoController = VideoController.network(...)
  });

在 C 或类似语言中,需要使用指针(或者我应该说我的首选方式)。要传递引用,请为其分配一个新值,然后处理旧值。

【问题讨论】:

标签: flutter dart


【解决方案1】:

Dart 不支持通过引用传递。 Dart 仅按值传递,就像 Java 一样。 Java 也不支持引用传递。

Java 是“按引用传递”还是“按值传递”?
https://stackoverflow.com/a/40523/1737201

下面是一个小证据。

void main() {
  // The variable "myVar" is a "lvalue" (storage of value)
  // Now we assign the value to "myVar" via "rvalue" "Object()"
  final myVar = Object();

  // Remember the old value
  final oldObject = myVar;

  // Now we will try to pass by reference.
  // We assume that we will pass the reference of storage ("lvalue")
  // ("myVar" im our case) because we cannot reference the value (pure data)
  // because the value does not contain storage location information.
  tryChangeMyVarByRef(myVar);

  // Check the result passing by reference
  // If storage of value was passed by its reference then changing
  // the value in this storage should have effect.
  assert(!identical(myVar, oldObject));

  // Epic fail because Dart does not support pass by refernce.
  print('WOW, it works!');
}

void tryChangeMyVarByRef(Object referencedStorgeOfValue) {
  // Try change the value stored in referenced storage of value
  referencedStorgeOfValue = Object();
}

编辑:

该值(或更正确的rvalue,表示没有任何存储的数据)不能有地址,因为该值只是一个数据。在编程中不可能引用数据(因为没有任何方法可以做到这一点),但可以引用数据的存储(例如变量的地址),因为存储总是有一些位置而不是数据(只能存储数据在某个位置但没有被引用,因为数据可以随时在这个位置被替换,因此这不能被称为对数据的引用,因为在执行数据重新分配后这可能是不正确的,但应该只被称为一些存储的引用数据)。

在编程中,术语“按引用传递”的意思是:传递值存储的引用(位置的地址)(即带有任何数据的某个变量的地址,但不传递该数据的地址)。 这允许 替换(但不仅仅是更改)存储在某个位置的数据,因为引用了存储(已知位置的地址)。

这仅意味着一件事:您传递存储某些值的变量的引用。

这并不意味着许多新手错误地认为的reference of some value(他们从未使用过 C 或 C++ 语言)。

另一个重要的事情是,在 Dart 中,对象(或实例)本身就是引用,因为它们是装箱的(值存储在堆中)。

这会产生您通过引用传递但同时您pass by value the reference 的错觉(其中作为值的引用是通过值传递的)。通过by value the reference 与通过by reference the reference 不同。

给新手的免费建议:学习 C 或 C++ 编程语言以找出以下内容之间的区别:

  • 通过by value the reference
  • 通过by reference the reference

在这两种情况下,值本身都是引用,但在第一种情况下,您按值传递值(引用),但在第二种情况下,您通过引用传递值(引用)。

享受吧!

【讨论】:

  • 如果我错了,请纠正我,但是...tryChangeMyVarByRef() 中发生的事情是 Object 的新实例被分配给变量 referencedStorgeOfValue 并且该变量的范围仅适用于它功能。这意味着您甚至没有尝试修改传入的对象,而是通过为 referencedStorgeOfValue 分配一个新值来丢弃对它的引用。
  • 不幸的是,谷歌从这个答案中选择了一行来回答“Dart 通过引用传递吗?”的问题。虽然在更大的上下文中答案是正确的,即 Dart 没有传递对 variable 的引用,但它确实传递了对原始 object 的引用。不幸的是,在 C++ 的上下文中,“按值传递”的含义是复制了对象,这是不正确的。
  • @JamesFoster 按引用传递:按引用传递(也称为按地址传递)是指将调用函数中的一个实参的引用传递给被调用函数的相应形参,以便复制实际参数的地址是在内存中创建的,即调用者和被调用者对参数使用相同的变量。如果被调用者修改了参数变量,效果对调用者的变量是可见的。
  • 我建议初学者参加短期课程,以开阔视野,提高知识水平。:Is Java “pass-by-reference” or “pass-by-value”?stackoverflow.com/questions/40480/…Dart在这方面与Java没有什么不同,这一切都适用于飞镖也是。
【解决方案2】:

抱歉,我的回答让您感到困惑。是的,在 Dart 中你使用对对象的引用,就像在 Java 中一样。我将给出一个简短的示例,让您清​​楚地了解为什么此代码可以按预期工作:

void main() {
  final t = Test(Test());
  t.removeField();
}

class Test {
  Test t;

  Future<void> removeField() async {
    print('current field: $t');

    Future.delayed(Duration(seconds: 2)).then((_) => print('delayed value: $t'));
    t = null;
  }

  Test([this.t]);
}

打印:

current field: Instance of 'Test'
delayed value: null

在这种情况下,首先将字段的值设置为 null,然后在 2 秒后执行回调。它访问对象的字段,但它已经为空。但如果我们这样做:

    final old = t;
    Future.delayed(Duration(seconds: 2)).then((_) => print('delayed value: $old'));

打印出来:

current field: Instance of 'Test'
delayed value: Instance of 'Test'

我们存储了该字段的先前值并将其传递给回调,因此它不会访问空字段。

【讨论】:

  • 在这种情况下,我应该在 Stateless/ful 小部件中将模型实例分配给 null 吗?例如:在有状态小部件内使用Person() 类创建的person 变量应在有状态小部件的dispose()? 内设置为null,还是flutter/GC/dart 会处理这个问题?
  • @AnsellC 在您之前的问题中,我提到您需要将其设置为 null,以确保小部件不再使用控制器。除此之外,您不需要在小部件状态的dispose() 内将每个字段都设置为 null,因为它们将与状态的实例一起被垃圾收集。但是有些东西需要手动处理,比如流订阅、控制器、监听器等。
  • 是的,我只是在思考如何释放资源,因为即使手动运行 GC,GC 也没有释放资源。
猜你喜欢
  • 2014-08-07
  • 2017-06-12
  • 2011-02-12
  • 2021-05-20
  • 2010-10-10
  • 2014-12-21
相关资源
最近更新 更多