小编Tie*_*inë的帖子

在重载算法中移动语义和Rvalue-Reference

我正在使用C++编写一个小型数值分析库.我一直在尝试使用最新的C++ 11功能实现,包括移动语义.我理解以下帖子中的讨论和最佳答案:C++ 11 rvalues和移动语义混淆(return语句),但有一种情况我仍然试图包围我的头脑.

我有一个类,称之为T,它配备了重载运算符.我也有复制和移动构造函数.

T (const T &) { /*initialization via copy*/; }
T (T &&) { /*initialization via move*/; }
Run Code Online (Sandbox Code Playgroud)

我的客户端代码大量使用运算符,所以我试图确保复杂的算术表达式从移动语义中获得最大的好处.考虑以下:

T a, b, c, d, e;
T f = a + b * c - d / e;
Run Code Online (Sandbox Code Playgroud)

没有移动语义,我的操作符每次都使用复制构造函数创建一个新的局部变量,所以总共有4个副本.我希望通过移动语义,我可以将其减少到2个副本加上一些动作.在括号中:

T f = a + (b * c) - (d / e);
Run Code Online (Sandbox Code Playgroud)

每个(b * c)并且(d / e)必须以通常的方式创建临时副本,但是如果我可以利用其中一个临时工具仅用移动来累积剩余的结果,那将是很好的.

使用g ++编译器,我已经能够做到这一点,但我怀疑我的技术可能不安全,我想完全理解为什么.

以下是加法运算符的示例实现:

T operator+ (T const& x) const
{
    T result(*this);
    // …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue-reference move-semantics c++11

12
推荐指数
2
解决办法
1781
查看次数

我的Fisher-Yates洗牌有什么问题吗?

意识到当一些东西看起来好得令人难以置信时,通常情况下,我想我会提出这个问题,希望能够清除掉任何一个小鬼.我回顾了一些我能找到的相关主题,但我的问题仍然存在.

我对Haskell相对较新,在我的实验中,我编写了一个基本的Fisher-Yates shuffle,如下所示.

shuffle :: RandomGen g => [a] -> g -> ([a],g)
shuffle [] g0 = ([],g0)
shuffle [x] g0 = ([x],g0)
shuffle xs g0 = (x:newtail,g2)
  where (i,g1) = randomR (0, length $ tail xs) g0
        (xs1,x:xs2) = splitAt i xs
        (newtail,g2) = shuffle (xs1++xs2) g1
Run Code Online (Sandbox Code Playgroud)

这个实现当然使用beaucoup内存用于大型列表,但它很快 - 在我的笔记本电脑上平均为5M,30M整数与标准C++混洗2.3s).事实上,它比其他地方的其他Haskell实现要快得多.(例如,http://www.haskell.org/haskellwiki/Random_shuffle)

鉴于我看到的其他Haskell shuffle既复杂又慢,我想知道加速/简单是否仅仅是我作为一个无懈可击的记忆猪的奖励,或者我是否错过了一些微小但关键的细节,使我的算法偏向.我没有进行过广泛的测试,但是初步看起来似乎显示了排列的均匀分布.

我希望通过更多Haskell和/或改组经验评估更多的眼睛.非常感谢所有花时间回复的人.

haskell shuffle

7
推荐指数
1
解决办法
622
查看次数

标签 统计

c++ ×1

c++11 ×1

haskell ×1

move-semantics ×1

rvalue-reference ×1

shuffle ×1