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

2022-04-14 16:00:38 +08:00
 fgwmlhdkkkw

问题是,

谢谢~

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

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

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

很快就连 C 语言也能用上这个属性( C23 )
en.cppreference.com/w/c/language/attributes/nodiscard
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
2022-04-14 22:53:24 +08:00
@fgwmlhdkkkw #4 我不太明白你的“不想复制”指的是啥。就我看来你这里用一个 std::vector<std::variant<std::string,int>>就能满足需求了的样子?
fgwmlhdkkkw
2022-04-15 09:48:21 +08:00
@lonewolfakela #12 你不说我都不知道,c++也有 union……谢谢
fgwmlhdkkkw
2022-04-15 09:53:05 +08:00
@lonewolfakela #12 那其实所有的变长参数都可以写成这种 vector ,应该要比模板展开好吧?
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
2022-04-15 10:28:28 +08:00
@lonewolfakela #12 variant 和 optinal 一样,只能保存值,不能保存引用。那所有的字符串不都会 copy 一下吗?
fgwmlhdkkkw
2022-04-15 10:49:38 +08:00
@fgwmlhdkkkw #16 我可以用`const char*`,可以了,只是多写一组大括号,完美。
lonewolfakela
2022-04-15 18:05:06 +08:00
@fgwmlhdkkkw #16 如果你是想保存引用的话,那你需要 std::vector<std::variant<std::reference_wrapper<std::string>,int>>

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/846957

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX