GVKun编程网logo

Swift数组分配不一致(既不是引用也不是深拷贝)是否有原因?(swift 数组)

29

本文将带您了解关于Swift数组分配不一致的新内容,同时我们还将为您解释既不是引用也不是深拷贝是否有原因?的相关知识,另外,我们还将为您提供关于8.7Swift类是引用类型、C#在foreach中重用

本文将带您了解关于Swift数组分配不一致的新内容,同时我们还将为您解释既不是引用也不是深拷贝是否有原因?的相关知识,另外,我们还将为您提供关于8.7 Swift类是引用类型、C# 在 foreach 中重用变量是否有原因?、celery + redis 是否存在任务分配不均的原因?、C#在foreach中重用变量是否有原因?的实用信息。

本文目录一览:

Swift数组分配不一致(既不是引用也不是深拷贝)是否有原因?(swift 数组)

Swift数组分配不一致(既不是引用也不是深拷贝)是否有原因?(swift 数组)

我正在阅读文档,并且不断对语言的一些设计决策摇头。但真正让我感到困惑的是数组是如何处理的。

我冲到操场上尝试了这些。你也可以试试。所以第一个例子:

var a = [1, 2, 3]var b = aa[1] = 42ab

Here aand bare both [1, 42, 3],我可以接受。数组被引用 - 好的!

现在看这个例子:

var c = [1, 2, 3]var d = cc.append(42)cd

c[1, 2, 3, 42]但是d[1, 2,3]。也就是说,d在上一个例子中看到了变化,但在这个例子中没有看到。文档说那是因为长度改变了。

现在,这个怎么样:

var e = [1, 2, 3]var f = ee[0..2] = [4, 5]ef

e[4, 5, 3],这很酷。有一个多索引替换很好,但f即使长度没有改变,仍然看不到变化。

总而言之,如果您更改 1 个元素,对数组的常见引用会看到更改,但如果您更改多个元素或附加项目,则会创建一个副本。

这对我来说似乎是一个非常糟糕的设计。我这样想对吗?有没有理由我不明白为什么数组应该这样?

编辑 :数组已更改,现在具有值语义。理智多了!

答案1

小编典典

请注意, Xcode beta 3 版本(博客文章) 中更改了数组语义和语法 ,因此该问题不再适用。以下答案适用于 beta
2:


这是出于性能原因。基本上,他们尽量避免复制数组(并声称“类似 C
的性能”)。引用语言书:

对于数组,仅当您执行可能修改数组长度的操作时才会进行复制。这包括追加、插入或删除项目,或使用范围下标替换数组中的一系列项目。

我同意这有点令人困惑,但至少对它的工作原理有一个清晰而简单的描述。

该部分还包括有关如何确保唯一引用阵列、如何强制复制阵列以及如何检查两个阵列是否共享存储的信息。

8.7 Swift类是引用类型

8.7 Swift类是引用类型

/**

类是引用类型

*/

/**

我们说Swift中的类和结构体非常的相似。

但是这个是表面的,它们背后的机制和原理在switf的设计中是完全不一样的。

*/

/**

下面将Swift中的 类和结构体最重要的不同点

类是引用类型,结构体是值类型。

类有继承 结构体没有继承

类有属性和行为 结构体也有属性和行为

*/

class Rect {

// 结构体成员变量

var width: Double = 5.0

var height: Double = 6.0

// 结构体的成员方法,可以访问使用成员属性。

func getWidth() -> Double {

return width

}

func show() -> Void {

print("width\(width)")

}

}


var rect1: Rect = Rect()

var rect2: Rect = rect1


print("---------------->")

print("rect1.width==\(rect1.width)")

print("rect1.height==\(rect1.height)")


// 改变rect1 的宽度

rect1.width = 100.0

print("rect2.width==\(rect2.width)")

print("rect2.height==\(rect2.height)")



/**

我们可以看到

rect1 赋给 rect2 后,改变 rect1的宽度,那么 rect2的宽度也改变了。

说明是让rect2指向rect1 也就是它们两个指向同一个实例。

说明类是引用类型

*/

C# 在 foreach 中重用变量是否有原因?

C# 在 foreach 中重用变量是否有原因?

在 C# 中使用 lambda 表达式或匿名方法时,我们必须警惕访问修改后的闭包陷阱。例如:

foreach (var s in strings){   query = query.Where(i => i.Prop == s); // access to modified closure   ...}

由于修改了闭包,上面的代码将导致Where查询中的所有子句都基于s.

正如这里所解释的,发生这种情况是因为上面循环中s声明的变量foreach在编译器中是这样翻译的:

string s;while (enumerator.MoveNext()){   s = enumerator.Current;   ...}

而不是这样:

while (enumerator.MoveNext()){   string s;   s = enumerator.Current;   ...}

正如这里所指出的,在循环之外声明变量没有性能优势,在正常情况下,我能想到这样做的唯一原因是如果您打算在循环范围之外使用变量:

string s;while (enumerator.MoveNext()){   s = enumerator.Current;   ...}var finalString = s;

然而,在循环中定义的变量foreach不能在循环外使用:

foreach(string s in strings){}var finalString = s; // won''t work: you''re outside the scope.

因此,编译器声明变量的方式使其极易出现通常难以发现和调试的错误,同时不会产生明显的好处。

有没有什么你可以用foreach这种方式来处理循环,如果它们是用内部范围的变量编译的,或者这只是在匿名方法和 lambda 表达式可用或常见之前做出的任意选择,并且没有从那以后就没有修改过?

答案1

小编典典

编译器声明变量的方式使其极易出现通常难以查找和调试的错误,同时不会产生明显的好处。

你的批评完全有道理。

如果使用内部范围的变量编译它们,您是否可以通过这种方式对 foreach 循环执行某些操作?或者这只是在匿名方法和 lambda 表达式可用或常见之前做出的任意选择,并且从那时起就没有修改过?

后者。C# 1.0 规范实际上并没有说明循环变量是在循环体内部还是外部,因为它没有明显的区别。在 C# 2.0 中引入闭包语义时,选择将循环变量放在循环之外,这与“for”循环一致。

我认为公平地说,所有人都对这个决定感到遗憾。这是 C# 中最糟糕的“陷阱”之一,我们将采取重大更改来修复它。在 C# 5 中,foreach 循环变量在逻辑上位于循环体中,因此闭包每次都会获得一个新副本。

for循环不会更改,更改不会“向后移植”到以前的 C# 版本。因此,在使用此成语时应继续小心。

celery + redis 是否存在任务分配不均的原因?

celery + redis 是否存在任务分配不均的原因?

如何解决celery + redis 是否存在任务分配不均的原因??

我们曾经使用 celery 任务队列系统将 redis 作为代理,将 rpc 作为后端。如果我们将 50 个任务发送给 5 个工人,那么每个工人最终会可靠地完成 10 个任务。 现在我们切换到redis作为后端和broker,有的worker拿到20个任务,有的拿到1个,似乎完全是随意的。除了后端 + 代理更改之外,没有任何代码更改。这有什么原因吗?

我运行的代码很简单:

from time import sleep
def multiply(self,num_1,num_2):
    sleep(50)
    return num_1 * num_2

我目前在 30 个节点上运行了 1000 次,有些工作人员正在运行 0 个任务,有些正在运行 11 个。我真的不明白为什么有些工作人员在队列中还有任务等待时会有 0 个任务运行。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

C#在foreach中重用变量是否有原因?

C#在foreach中重用变量是否有原因?

在C#中使用lambda表达式或匿名方法时,我们必须警惕 对修改后的闭包 陷阱的 访问 。例如:

foreach (var s in strings){   query = query.Where(i => i.Prop == s); // access to modified closure   ...}

由于修改后的闭包,上述代码将导致Where查询中的所有子句都基于的最终值s

正如解释在这里,这是因为该s变量在声明foreach环以上的编译器编译如下:

string s;while (enumerator.MoveNext()){   s = enumerator.Current;   ...}

而不是像这样:

while (enumerator.MoveNext()){   string s;   s = enumerator.Current;   ...}

如此处所指出的,在循环外声明变量没有性能优势,在正常情况下,我能想到的唯一原因是如果您打算在循环范围外使用变量:

string s;while (enumerator.MoveNext()){   s = enumerator.Current;   ...}var finalString = s;

但是,foreach循环中定义的变量不能在循环外使用:

foreach(string s in strings){}var finalString = s; // won''t work: you''re outside the scope.

因此,编译器以某种方式声明该变量,使其极易出现通常难以查找和调试的错误,同时不会产生明显的收益。

是否可以通过foreach这种方式对循环执行某些操作,如果它们是使用内部作用域变量进行编译则无法做到的,或者这只是在匿名方法和lambda表达式可用或通用之前做出的任意选择,并且没有从那以后就没有修改过?

答案1

小编典典

编译器以一种很容易出错的方式声明该变量,该错误通常很难查找和调试,同时不会产生明显的好处。

您的批评是完全有道理的。

我在这里详细讨论这个问题:

关闭循环变量被认为是有害的

使用foreach循环,是否可以通过内部作用域变量进行编译而无法做到?还是这只是在匿名方法和lambda表达式可用或通用之前做出的任意选择,并且此后没有进行过修改?

后者。实际上,C#1.0规范没有说明循环变量是在循环体内还是在循环体内,因为它没有明显的区别。在C#2.0中引入闭包语义时,已做出选择,将循环变量置于循环之外,与“
for”循环一致。

我认为可以说所有人都对该决定表示遗憾。这是C#中最糟糕的“陷阱”之一, 我们将进行重大更改来修复它。 在C#5中,foreach循环变量在逻辑上将
位于 循环体内,因此闭包每次都会获得新的副本。

for循环将不会改变,并且改变不会是“向后移植”到C#的早期版本。因此,在使用此惯用语时,您应继续小心。

今天关于Swift数组分配不一致既不是引用也不是深拷贝是否有原因?的讲解已经结束,谢谢您的阅读,如果想了解更多关于8.7 Swift类是引用类型、C# 在 foreach 中重用变量是否有原因?、celery + redis 是否存在任务分配不均的原因?、C#在foreach中重用变量是否有原因?的相关知识,请在本站搜索。

本文标签: