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

自己写了一个 JSON 解析器,遇到一个问题

  •  
  •   fgwmlhdkkkw · 2022-04-14 16:00:38 +08:00 · 2539 次点击
    这是一个创建于 985 天前的主题,其中的信息可能已经有所发展或是发生改变。

    LlTXqS.png

    问题是,

    • C++是不是没有办法实现变长参数?
    • 图片里的这种方式最终是不是会变成很多个函数的相互调用?
    • 但我给每个函数都加了 inline ,会有什么影响吗?

    谢谢~

    18 条回复    2022-04-15 18:05:06 +08:00
    fgwmlhdkkkw
        1
    fgwmlhdkkkw  
    OP
       2022-04-14 16:08:36 +08:00
    有编译器会尝试把这种写法变成一个循环吗?
    codehz
        2
    codehz  
       2022-04-14 16:31:26 +08:00 via Android   ❤️ 1
    你写类定义里默认就是 inline ,用模板基本上逃不了 inline 了,然后 inline 的语义是允许在不同翻译单元重复定义,不是“不生成函数原地展开”,能不能展开看编译器心情
    lonewolfakela
        3
    lonewolfakela  
       2022-04-14 16:35:01 +08:00   ❤️ 1
    1 、你写的这个不就是变长参数?
    2 、是。
    3 、几乎没啥影响……可能让某些编译器的优化步骤中对函数内联稍微激进一点点,但是效果可以忽略不计。
    4 、尾递归确实很可能被优化掉,但是优化器的事情没人敢打包票;虽然我觉得如果你这个实际跑起来没啥问题的话就这样也挺好。
    5 、真要是觉得递归看起来实在难看的话,可以学习一下 https://en.cppreference.com/w/cpp/language/fold 的用法
    6 、你为什么不把变长参数放在一个 std::vector 里传进去呢……
    fgwmlhdkkkw
        4
    fgwmlhdkkkw  
    OP
       2022-04-14 16:48:55 +08:00
    @codehz #2 我一直以为 inline 是“尽可能的 define”。
    @lonewolfakela #3 谢谢,vector 的话,我要为数字和字符串做一个包装类。问题是在这个包装类里怎么储存字符串?(我不想复制)。
    cnbatch
        5
    cnbatch  
       2022-04-14 17:31:26 +08:00
    不想复制的话,可以使用万能引用、完美转发

    template <typename T, typename ... Args>
    [[nodiscard]]
    const Value * peek(const Value * src, T key, Args && ... args)
    {
    // auto 和 if 的部分
    // ......
    return peek(ptr, std::forward<Args>(args)...);
    }
    fgwmlhdkkkw
        6
    fgwmlhdkkkw  
    OP
       2022-04-14 17:44:58 +08:00
    @cnbatch #5 额,左值右值,值晕了~
    whitehack
        7
    whitehack  
       2022-04-14 17:47:40 +08:00
    感觉已经完全不会 c++了.

    这 [[nodiscard]] 是啥语法.. 还是两个 中括
    fgwmlhdkkkw
        8
    fgwmlhdkkkw  
    OP
       2022-04-14 17:49:37 +08:00
    @whitehack #7 ……Clion 教我加的😓
    fgwmlhdkkkw
        9
    fgwmlhdkkkw  
    OP
       2022-04-14 17:50:41 +08:00
    @whitehack #7 意思是,调用者不能忽略这个函数的返回值。
    cnbatch
        10
    cnbatch  
       2022-04-14 18:03:19 +08:00   ❤️ 1
    @whitehack [[nodiscard]]的意思楼上已经说了,那我就稍作补充。

    这是 C++17 新属性
    en.cppreference.com/w/cpp/language/attributes/nodiscard

    很快就连 C 语言也能用上这个属性( C23 )
    en.cppreference.com/w/c/language/attributes/nodiscard
    cnbatch
        11
    cnbatch  
       2022-04-14 18:38:31 +08:00
    @fgwmlhdkkkw 忘了补一个 T key 的万能引用

    const Value * peek(const Value * src, T key, Args && ... args)

    可以适当改成

    const Value * peek(const Value * src, T && key, Args && ... args)
    {
    auto ptr = peek(src, std::forward(key));
    if (ptr == nullptr) return nullptr;
    return peek(ptr, std::forward<Args>(args)...);
    }

    至于应不应该改,那就视乎你的具体需要而定
    lonewolfakela
        12
    lonewolfakela  
       2022-04-14 22:53:24 +08:00
    @fgwmlhdkkkw #4 我不太明白你的“不想复制”指的是啥。就我看来你这里用一个 std::vector<std::variant<std::string,int>>就能满足需求了的样子?
    fgwmlhdkkkw
        13
    fgwmlhdkkkw  
    OP
       2022-04-15 09:48:21 +08:00
    @lonewolfakela #12 你不说我都不知道,c++也有 union……谢谢
    fgwmlhdkkkw
        14
    fgwmlhdkkkw  
    OP
       2022-04-15 09:53:05 +08:00
    @lonewolfakela #12 那其实所有的变长参数都可以写成这种 vector ,应该要比模板展开好吧?
    lonewolfakela
        15
    lonewolfakela  
       2022-04-15 10:19:40 +08:00
    @fgwmlhdkkkw #14 仅就你这个应用场景,我觉得 vector 更好。但是也有一些其他场景下更适合用模板,不然函数用起来会很难看(参考 https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification ,这种 format 函数如果参数也用 vector 来传的话用起来肯定特别难受)。
    不过总的一般原则是优先考虑代码写起来美观、顺手,而不是优先考虑编译器会不会内联、编译出来的代码快不快之类问题;性能问题一般不要过早优化,代码写出来了如果确定有性能瓶颈的话再针对性优化。
    fgwmlhdkkkw
        16
    fgwmlhdkkkw  
    OP
       2022-04-15 10:28:28 +08:00
    @lonewolfakela #12 variant 和 optinal 一样,只能保存值,不能保存引用。那所有的字符串不都会 copy 一下吗?
    fgwmlhdkkkw
        17
    fgwmlhdkkkw  
    OP
       2022-04-15 10:49:38 +08:00
    @fgwmlhdkkkw #16 我可以用`const char*`,可以了,只是多写一组大括号,完美。
    lonewolfakela
        18
    lonewolfakela  
       2022-04-15 18:05:06 +08:00
    @fgwmlhdkkkw #16 如果你是想保存引用的话,那你需要 std::vector<std::variant<std::reference_wrapper<std::string>,int>>
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5173 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 01:20 · PVG 09:20 · LAX 17:20 · JFK 20:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.