V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
twor2
V2EX  ›  程序员

2B程序员2在哪里了?

  •  
  •   twor2 · 2013-06-30 17:19:42 +08:00 · 5687 次点击
    这是一个创建于 4168 天前的主题,其中的信息可能已经有所发展或是发生改变。
    50 条回复    1970-01-01 08:00:00 +08:00
    typing
        1
    typing  
       2013-06-30 17:22:27 +08:00 via iPad
    你试试看交换没有
    fly2never
        2
    fly2never  
       2013-06-30 17:22:49 +08:00   ❤️ 1
    注意看函数参数
    另外文艺那个才是真2B
    zsj950618
        3
    zsj950618  
       2013-06-30 17:23:17 +08:00
    the third function can't work!
    alexrezit
        4
    alexrezit  
       2013-06-30 17:29:25 +08:00
    普通和文艺哪个更快呢? 我的很多代码都是用类似文艺方法写的, 不知道对速度有木有影响.
    twor2
        5
    twor2  
    OP
       2013-06-30 17:40:37 +08:00
    @alexrezit 我们俩巨大差异, 一个2b 一个文艺,唉
    fangzhzh
        6
    fangzhzh  
       2013-06-30 17:53:45 +08:00   ❤️ 1
    2b程序这样解释, a和b要交换体液,结果各自派了替身,白忙活了,都没有爽到...
    timonwong
        7
    timonwong  
       2013-06-30 17:55:37 +08:00
    @alexrezit
    性能上临时变量稍微快一点点,不过没有显著影响。
    另外,xor swap效果与tmp var swap效果不同:如果 a 和 b 引用同一个变量,该变量会被清零。
    yuanz
        8
    yuanz  
       2013-06-30 18:06:50 +08:00
    第一个 void swap(int &a, int &b) 是什么写法, int &a 这个形式是什么意思?求解释...
    luikore
        9
    luikore  
       2013-06-30 18:16:00 +08:00
    其实文艺程序员那个不仅有 bug, 还可能会慢一点

    因为变量仅仅是名字而已, 很多 swap 代码可以被编译器优化成没 swap 的

    clang++ -O3 -c -S 看看汇编的差别就知道了
    luikore
        10
    luikore  
       2013-06-30 18:18:51 +08:00
    如果某个奇技淫巧真的有优化作用, 就已经写进编译器里了, 不要自己白忙活啦...
    msg7086
        11
    msg7086  
       2013-06-30 18:44:20 +08:00   ❤️ 1
    @yuanz C++ 引用

    @alexrezit 编译器会用比xor更快的方法实现,比如用XCHG汇编之类的。或者直接在后续的指令中使用新的内存地址引用。
    qiukun
        12
    qiukun  
       2013-06-30 18:44:41 +08:00
    @alexrezit 这个文艺方法 bug 在于 0
    swulling
        13
    swulling  
       2013-06-30 18:48:57 +08:00
    @yuanz 取地址运算符,找本c的入门书看看
    ls2110609
        14
    ls2110609  
       2013-06-30 18:49:35 +08:00
    @fly2never 2在哪?...
    swulling
        15
    swulling  
       2013-06-30 18:49:50 +08:00   ❤️ 1
    @yuanz 眼花了,这个C++
    msg7086
        16
    msg7086  
       2013-06-30 18:50:55 +08:00
    @swulling 关于这个问题我特地去查了一下,明确告诉你,

    Address-of Operator: &
    Reference Operator: &

    这是两个功能不同但是写法相同的运算符
    swulling
        17
    swulling  
       2013-06-30 18:53:12 +08:00
    @msg7086 没看我回复了么。。眼花了,不用普及这个。。。

    用取地址也能swap,不过是c写法
    msg7086
        18
    msg7086  
       2013-06-30 18:55:01 +08:00
    @swulling 看到了。前面回复的时候被你插楼的。取地址需要传指针嘛,C++简化了这个操作。
    davepkxxx
        19
    davepkxxx  
       2013-06-30 19:26:08 +08:00
    void swap(int a, int b) 这种写法是指针传递。

    指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

    void swap(int &a, int &b) 这种写法是引用传递。

    在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

    想要了解跟多请参考C++的指针和引用传递相关内容。
    davepkxxx
        20
    davepkxxx  
       2013-06-30 19:27:21 +08:00
    第二种写法是什么意思?没看懂。
    ls2110609
        21
    ls2110609  
       2013-06-30 19:37:32 +08:00
    @davepkxxx 你试一试 会惊奇的发现这同样是换值 用了位运算 但是有局限性 比如 0
    jjplay
        22
    jjplay  
       2013-06-30 19:49:21 +08:00
    给你贴个我之前公司的程序员弄得js代码

    $(document).ready(function() {
    $("#example1-1").imgbox();
    });
    $(document).ready(function() {
    $("#example1-2").imgbox();
    });
    $(document).ready(function() {
    $("#example1-3").imgbox();
    });
    $(document).ready(function() {
    $("#example1-4").imgbox();
    });
    $(document).ready(function() {
    $("#example1-5").imgbox();
    });
    $(document).ready(function() {
    $("#example1-6").imgbox();
    });
    )};

    ----------------------------------------------
    为毛他就是想不到 for循环
    Golevka
        23
    Golevka  
       2013-06-30 19:51:00 +08:00
    @alexrezit 文艺方法是错的, 当a和b引用同一个变量时a和b都会变成0
    txx
        24
    txx  
       2013-06-30 20:00:56 +08:00
    文艺程序员这个 曾经还有一句话版本的....同样也有bug的....
    一般这么写都是用于 acm 大神装逼
    而不是用在工程开发上
    fangzhzh
        25
    fangzhzh  
       2013-06-30 20:05:40 +08:00 via Android
    @davepkxxx 第一个传值 第二个传引用 传地址是另外的 用*的
    treo
        26
    treo  
       2013-06-30 20:28:59 +08:00
    swap的标准做法不是xor吗
    alexrezit
        27
    alexrezit  
       2013-06-30 20:33:10 +08:00
    @qiukun
    @Golevka
    呃... 我是说类似的意思是避免使用 temp var.
    yuanz
        28
    yuanz  
       2013-06-30 20:56:48 +08:00
    @msg7086 thx! 不懂C++,还以为是C语言的,于是以为是错了...汗.
    yuanz
        29
    yuanz  
       2013-06-30 20:58:09 +08:00
    @swulling 谢~
    luikore
        30
    luikore  
       2013-06-30 21:43:51 +08:00
    @alexrezit 那对速度也没影响... 编译器基本都有个优化阶段是把代码变成 SSA 形式, SSA 形式所有 var 都只赋值一遍, 或者说就是一大堆 tmp var... 单赋值的代码上面可以做各种优化, 所以 LLVM 的中间语言就是用 SSA 的

    http://en.wikipedia.org/wiki/Static_single_assignment_form
    celon
        31
    celon  
       2013-06-30 21:52:07 +08:00
    使用第二种方法,才是二逼程序员吧?!
    我本身参与维护的一个老旧开源项目,里面这种类似写法数不胜数。
    celon
        32
    celon  
       2013-06-30 21:53:03 +08:00   ❤️ 1
    补充:
    我的意思是:写出不能让人一下子看明白的代码,本身是一种二逼行为。
    luikore
        33
    luikore  
       2013-06-30 21:56:04 +08:00   ❤️ 1
    @alexrezit

    SSA 在分配寄存器阶段才做消除的
    如果你脑内分配的结果比寄存器分配算法出来的快, 也可以用 asm ("RIP") 之类的去强制指定变量对应的寄存器, 但是不用内联汇编的话, 就算给变量加 register 关键字, 用不用 temp var 也对结果速度几乎没影响.

    C++ 里是有复制构造函数的坑, 但是把重量级类型的 temp var 声明成引用类型就没事了.
    luikore
        34
    luikore  
       2013-06-30 22:09:56 +08:00   ❤️ 2
    现代 C 编译器已经打败了上个世纪的各种 2B 优化方式, KISS 的代码往往就是最高效的代码

    再举个例子... 如 strcmp 的实现, 网上有大量的陈年博客写是如何强制转换成多字节类型来提速的, 但现在的情况是写成最笨的一个个字节比较的方式反而可能更快. 因为编译器可以做 loop unroll 然后根据 CPU 的 flag 选择 AVX2 / AVX / SIMD2 / SIMD1 指令去搞, 比手工优化来得安全, 而且自动选择了最佳匹配的指令, 速度和跨平台都能兼顾.
    Mutoo
        35
    Mutoo  
       2013-06-30 23:18:39 +08:00
    哈哈哈哈
    davepkxxx
        36
    davepkxxx  
       2013-07-01 01:19:32 +08:00
    @fangzhzh 谢谢指正,我太久没碰c了……
    Hyperion
        37
    Hyperion  
       2013-07-01 01:26:33 +08:00
    @jjplay for也不大好, 不多的话写一起不就好了...
    so898
        38
    so898  
       2013-07-01 01:27:20 +08:00
    写Objective-C和Java写多了之后,竟然觉得最后一个最顺眼……
    我就这样『被2B』了么……
    XDA
        39
    XDA  
       2013-07-01 09:39:22 +08:00
    void swap(int x, int y)
    {
    x = x + y;
    y = x - y;
    x = x - y;
    }
    ————————————————————————————
    这个写法是不是也很2B?
    Fedor
        40
    Fedor  
       2013-07-01 10:57:51 +08:00
    @jjplay 为毛他不看jq手册

    $('#a, #b').lightbox();
    Hyperion
        41
    Hyperion  
       2013-07-01 10:59:35 +08:00
    @XDA 少年, 会溢出...
    felix021
        42
    felix021  
       2013-07-01 11:53:51 +08:00
    @fly2never 文艺那个好像没错,这个是C++的引用,不是C的指针。。
    felix021
        43
    felix021  
       2013-07-01 11:54:19 +08:00
    @XDA 是的,因为会溢出,不能保证正确。
    darasion
        44
    darasion  
       2013-07-01 12:16:37 +08:00
    好复杂,看不懂耶
    XDA
        45
    XDA  
       2013-07-01 12:26:28 +08:00
    ————————————————————
    @Hyperion @felix021 那还是这种:
    a^=b;
    b^=a;
    a^=b;
    ————————————————————
    kaichen
        46
    kaichen  
       2013-07-01 12:34:27 +08:00
    @luikore 好像没人理你
    twor2
        47
    twor2  
    OP
       2013-07-01 13:02:12 +08:00
    @luikore

    @kaichen

    没人理,只是没有槽点,不代表没价值。都仔细看过了,非常感谢 @luikore
    VeryCB
        48
    VeryCB  
       2013-07-01 13:36:24 +08:00
    a, b = b, a
    Hyperion
        49
    Hyperion  
       2013-07-01 19:16:56 +08:00
    @XDA 这种做法完全没有问题, 不过从来不这么干... 其实中间变量有毛不好?

    另外吐槽, 这个做法bug的确会有, 但两个变量一个地址你还去swap... 思维正常的人会这么干吗?
    atempcode
        50
    atempcode  
       2013-07-01 19:25:50 +08:00 via Android
    2在B前面。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1130 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:54 · PVG 06:54 · LAX 14:54 · JFK 17:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.