首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >D中的容器语义和函数风格

D中的容器语义和函数风格
EN

Stack Overflow用户
提问于 2012-10-31 18:12:14
回答 2查看 215关注 0票数 3

默认情况下,D中的容器是否具有值或引用语义?如果它们有引用语义,那就不会从根本上阻碍在D中使用函数式编程风格(与C++11的移动语义相比),例如在下面的(学术)示例中:

代码语言:javascript
复制
auto Y = reverse(sort(X));

其中X是一个容器。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-01 02:34:39

容器是否具有值语义或引用语义完全取决于容器。唯一的内置容器是动态数组、静态数组和关联数组。静态数组具有严格的值语义,因为它们位于堆栈上。关联数组有严格的引用语义。并且动态数组大多具有引用语义。它们的元素不会被复制,但它们确实会被复制,所以它们以有点特殊的语义结束。我建议阅读关于D数组的this article以了解更多细节。

对于正式的但不是内置的容器,std.container中的容器都有引用语义,通常情况下,容器应该是引用语义,因为否则效率非常低。但由于任何人都可以实现自己的容器,所以任何人都可以创建属于值类型的容器。

然而,像C++一样,D没有采用让算法在容器上操作的路线,所以就算法而言,容器是否具有引用或值语义几乎是无关紧要的。在C++中,算法在迭代器上操作,所以如果您想对容器进行排序,可以执行类似sort(container.begin(), container.end())的操作。在D中,它们在范围上操作,所以你可以使用sort(container[])。在这两种语言中,您实际上都不会直接对容器进行排序。因此,容器本身是否具有值或引用语义与您的典型算法无关。

然而,D在使用算法进行函数式编程方面比C++做得更好,因为范围更适合它。迭代器必须成对传递,这对于链式函数不是很有效。另一方面,Range的链条非常好,Phobos利用了这一点。它的主要设计原则之一是它的大多数函数都在范围内操作,允许你在代码中做你通常在unix命令行上使用管道所做的事情,其中你有很多通用的工具/函数生成输出,你可以通过管道/传递到其他工具/函数进行操作,允许你链接独立的操作来做一些特定于你需要的事情,而不是依赖于某人编写的程序/函数直接做你想要的事情。沃尔特·布赖特最近在this article上讨论了这一问题。

因此,在D中,很容易做到如下所示:

代码语言:javascript
复制
auto stuff = sort(array(take(map!"a % 1000"(rndGen()), 100)));

或者,如果您更喜欢UFCS (通用函数调用语法):

代码语言:javascript
复制
auto stuff = rndGen().map!"a % 1000"().take(100).array().sort();

在任何一种情况下,它都会生成一个包含100个介于0和1000之间的随机数的排序列表,并且代码是函数式的,这是C++很难做到的,而对容器而不是迭代器或范围进行操作的库将更难做到。

票数 4
EN

Stack Overflow用户

发布于 2012-11-01 00:06:06

内置容器

D中唯一的内置容器是切片(也称为数组/动态数组)和静态数组。后者具有值语义(与C和C++不同)-传递时整个数组被(浅)复制。

至于切片,它们是具有间接性的值类型,因此您可以说它们同时具有值语义和引用语义。

T[]想象成这样的struct

代码语言:javascript
复制
struct Slice(T)
{
    size_t length;
    T* ptr;
}

其中ptr是指向切片的第一个元素的指针,length是切片边界内的元素数。您可以访问片的.ptr.length字段,但是虽然数据结构与上面的完全相同,但它实际上是一个内置的编译器,因此没有在任何地方定义(名称Slice只是为了说明目的)。

了解了这一点,您可以看到复制切片(赋值给另一个变量,传递给函数等)只复制一个长度(无缩进-值语义)和一个指针(具有间接引用语义)。

换句话说,切片是数组(位于内存中的任何位置)中的视图,并且可以有多个视图到同一数组中。

算法

来自std.algorithmsortreverse就地工作,以迎合尽可能多的用户。如果用户希望将结果放在切片的GC分配的副本中,并保持原始切片不变,那么很容易做到这一点(X.dup)。如果用户想要将结果放在自定义分配的缓冲区中,也可以这样做。最后,如果用户想要就地排序,这是一个选择。无论如何,任何额外的开销都是显式的。

但是,重要的是要注意,标准库中的大多数算法不需要突变,而是返回延迟计算的范围结果,这是函数式编程的特征。

用户定义的容器

当涉及到用户定义的容器时,它们可以拥有任何他们想要的语义--任何配置都可以在D中实现。

std.container中的容器是引用类型,带有用于制作副本的.dup方法,因此稍微模仿了切片。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13155587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档