在Matlab中,我试图将匿名函数放入数组中:
>> a=[@(k)0.1/(k+1) @(k)0.1/(k+1)^0.501]
??? Error using ==> horzcat
Nonscalar arrays of function handles are not allowed; use cell arrays
instead.
所以我想知道数组和单元格数组中允许哪些元素?
例如,我知道在一个数组中,元素可以是数字或字符串。还有什么?
简而言之:单元数组是异构容器,正则数组是同构。这意味着在规则数组中,所有元素都是相同类型的,而在单元数组中,它们可以不同。您可以在这里阅读更多关于单元阵列的信息。
当:时使用单元格阵列
- 数组中有不同的类型
- 您不确定将来是否可以将其扩展到其他类型
- 您正在处理具有继承模式的对象
- 您使用的是字符串数组-几乎在任何情况下,都最好使用char(n,m)
- 您有一个大数组,并且经常更新函数中的单个元素-由于Matlabs写时复制策略
- 您正在使用函数句柄(正如@Pursuit所解释的)
当:时,首选正则数组
- 所有元素都具有相同的类型
- 您在一次类似于数学运算的操作中更新整个数组
- 你想要类型安全
- 将来不会更改数组的数据类型
- 您正在使用数学矩阵
- 您正在处理没有继承的对象
关于写时复制的更多解释:
将数组传递给函数时,将传递指针/引用。
function foo(x)
disp(x);
end
x= [1 2 3 4 5];
foo(x); %No copy is done here! A pointer is passed.
但是,当您更改它(或它的一部分)时,就会创建一个副本。
function foo(x)
x(4) = x(4) + 1;
end
x= [1 2 3 4 5];
foo(x); %x is being copied! At least twice memory amount is needed.
在单元阵列中,仅复制单元。
function foo(x)
x{4} = x{4} + 1;
end
x= {1 2 3 4 5}; %Only x{4} will be copied
因此,如果您调用一个函数来更改大型数组中的单个元素,则会产生大量副本,这会使其速度变慢。但在细胞阵列中,情况并非如此。
函数句柄实际上是这里的例外,原因是如果允许函数句柄成为非单元数组的一部分,Matlab语法会变得令人惊讶。例如
a = @(x)x+1;
a(2); %This returns 2
但是,如果支持函数句柄数组,那么
b = [@(x)x+1, @(x)x+2];
b(2); %This would return @(x)x+2
b(3) = @(x)x+3; %This would extend the size of the array
那么这是允许的吗?
a(2) = @(x)x+2; %Would this extend the size of the previously scalar array
长时间编辑:这在R14的发行说明中有记载,R14是第一个允许匿名函数的发行版。在R14之前,您可以创建函数句柄作为m文件函数的引用,并且它们可以放置在非单元数组中。这些只能使用feval
(例如:fnSin = @sin; output = feval(fnSin, pi)
)来调用。
当引入匿名函数时,Mathworks更新了语法,以允许更简单的调用约定(例如fnSin = @sin; output = fnSin(pi)
),这在使用函数句柄的非单元数组时会导致歧义。看起来他们已经尽了最大努力来宣传这种新行为,但那些被宣传的条件肯定已经过期了(这是2004年)。
数组只能存储固定长度的数据。例如,double、single、char、logic、integer。原因是(我想)它们直接存储在一个内存块中。另一方面,单元格存储为指针列表,每个指针可以指向不同大小的数据。
这就是数组不能存储字符串、函数句柄、数组和多种数据类型的原因。这些类型可以有不同的长度。例如,'bla'有3个字节,'blabla'有6个字节。因此,如果它们存储在同一个内存块中,如果您想将"bla"更改为"blabla",则必须移动内存的所有其余部分,这将非常缓慢,因此无法处理。