使用索引/范围对数组进行切片是不是会创建数组的副本

Posted

技术标签:

【中文标题】使用索引/范围对数组进行切片是不是会创建数组的副本【英文标题】:Does slicing an array using Index/Range create a copy of the array使用索引/范围对数组进行切片是否会创建数组的副本 【发布时间】:2019-10-10 20:33:39 【问题描述】:

随着 C# 8.0 引入了结构体 IndexRange,我们现在可以轻松获得数组的切片,执行类似的操作

string[] baseArray = "a","b", "c", "d", "e", "f";

var arr = baseArray[1..^2];

像这样对数组进行切片会复制数组吗?或者它没有像ArraySegment<T>那样复制吗?

【问题讨论】:

你的测试不是真的有效。您所做的只是创建结构,而不是使用它们。例如,Linq 版本只返回一个IEnumerable,但实际上并没有做任何事情。 @DavidG 好的,感谢您指出这一点。删除了我的测试用例。然而,原来的问题仍然存在,它是否复制了数组? 【参考方案1】:

自己试试吧:

string[] baseArray =  "a", "b", "c", "d", "e", "f" ;
var arr = baseArray[1..^2];
Debug.WriteLine(arr[0]);
Debug.WriteLine(baseArray[1]);
arr[0] = "hello";
Debug.WriteLine(arr[0]);
Debug.WriteLine(baseArray[1]);

输出

b
b
hello
b

我们可以断定 string 数组被复制了。

但是,如果我们使用对象数组:

public class Foo

    public string Bar  get; set; 


Foo[] baseArray =

    new Foo  Bar = "a" ,
    new Foo  Bar = "b" ,
    new Foo  Bar = "c" ,
    new Foo  Bar = "d" ,
    new Foo  Bar = "e" ,
    new Foo  Bar = "f" 
;

var arr = baseArray[1..^2];
Debug.WriteLine(arr[0].Bar);
Debug.WriteLine(baseArray[1].Bar);
arr[0].Bar = "hello";
Debug.WriteLine(arr[0].Bar);
Debug.WriteLine(baseArray[1].Bar);

arr[0] = new Foo  Bar = "World" ;
Debug.WriteLine(arr[0].Bar);
Debug.WriteLine(baseArray[1].Bar);

这个输出

b
b
hello
hello
World
hello

数组中的对象不会被复制而是被引用。

在数组中设置另一个对象不会影响另一个。

【讨论】:

以上是关于使用索引/范围对数组进行切片是不是会创建数组的副本的主要内容,如果未能解决你的问题,请参考以下文章

窥探Swift之数组安全索引与数组切片

关于 python 何时自动创建数组副本的文档

通过python中的索引和数组对数据框进行切片

将 Pandas DataFrame 切片成新的 DataFrame

尝试对数组进行切片会导致“数组索引过多”。我可以填充阵列来解决这个问题吗?

Objective-C 对数组进行切片会导致索引越界错误