如何在语言级别将变量标记为已初始化?
How to mark a variable as initialized at the language level?
我正在使用链接的 C 库将值放入变量中。
void f_wrapper(int& v){
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
}
...
int value; // clang-tidy complains here: using "variable 'value' is not initialized"
f_wrapper(value);
然而,clang-tidy 在这里抱怨:使用“变量 'value' 未初始化”。
据了解,这仅仅是因为编译器无法看穿链接函数。
我不想做 int value = 0
(因为我相信库会初始化 value
并且我相信“部分形成”的值。)
另外,我希望不要添加 // NOLINT(warning)
只是为了抑制警告。
(该模式经常重复。)
有什么我可以用语言将value
标记为已初始化吗?
我正在寻找类似的东西:
void f_wrapper(int& v) {
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
[[mark initialized(v)]];
}
最坏的情况我可以在包装器内部做到这一点,因为至少我没有看到主代码中不必要的初始化,但是在数组是初始化。我也不想为此初始化付出代价或选择默认值。
void f_wrapper(int& v) {
v = int{}; // initialize to suppress warning at high level code
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
}
这不是您想听到的,但实际上只有 一种 方法可以在标准 C++ 中“在语言级别”初始化变量——那就是 初始化它。这真的很简单。正如您在问题中已经描述的那样,您基本上要么坚持这个,要么 NOLINT
ing 它。这不是一个迷人的解决方案,也不是您所追求的;但真的没有更好的办法了。
我确信可能有一些方法可以“欺骗”工具,使其认为它已初始化,但任何此类建议充其量只是黑客攻击。
也就是说;假设导致悲伤的 clang-tidy
检查是 cppcoreguidelines-init-variables
规则,值得注意的是这个 仅 触发整数、布尔值、浮点数、双精度数和指针 - 和默认初始化这样一个值的成本通常可以忽略不计。除非您已对该成本进行基准测试并发现默认初始化这是一个 真正的瓶颈 ,否则几乎没有理由避免这种做法。
一般来说,初始化变量是解决这个问题最干净/最安全的方法,最终也是最佳实践无论如何。没有初始化,只需要 small f_legacy
中的错误即可导致意外的 UB。如果 f_legacy
有任何错误使得它 return 成功但忘记将值设置为 v
,那么 v
将不会被初始化并且将正式成为 UB -- 并且这只是为了保存默认初始化原语。
只是一个建议:
根据您的“最坏情况”f_wrapper
示例,NOLINT
调用调用者或必须初始化其他人的未初始化值,API 是否可以更改到 return 初始化值而不是初始化传入的内容?
如果您这样做,您可以在内部 NOLINT
它,因此需要的 NOLINT
更少,或者您自己初始化该值以防止其他潜在问题。由于该值被封装在函数中,因此这比初始化调用者的可能未初始化的值要简单得多,在我看来:
int f_wrapper() {
auto v = int{};
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
return v;
}
我正在使用链接的 C 库将值放入变量中。
void f_wrapper(int& v){
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
}
...
int value; // clang-tidy complains here: using "variable 'value' is not initialized"
f_wrapper(value);
然而,clang-tidy 在这里抱怨:使用“变量 'value' 未初始化”。
据了解,这仅仅是因为编译器无法看穿链接函数。
我不想做 int value = 0
(因为我相信库会初始化 value
并且我相信“部分形成”的值。)
另外,我希望不要添加 // NOLINT(warning)
只是为了抑制警告。
(该模式经常重复。)
有什么我可以用语言将value
标记为已初始化吗?
我正在寻找类似的东西:
void f_wrapper(int& v) {
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
[[mark initialized(v)]];
}
最坏的情况我可以在包装器内部做到这一点,因为至少我没有看到主代码中不必要的初始化,但是在数组是初始化。我也不想为此初始化付出代价或选择默认值。
void f_wrapper(int& v) {
v = int{}; // initialize to suppress warning at high level code
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
}
这不是您想听到的,但实际上只有 一种 方法可以在标准 C++ 中“在语言级别”初始化变量——那就是 初始化它。这真的很简单。正如您在问题中已经描述的那样,您基本上要么坚持这个,要么 NOLINT
ing 它。这不是一个迷人的解决方案,也不是您所追求的;但真的没有更好的办法了。
我确信可能有一些方法可以“欺骗”工具,使其认为它已初始化,但任何此类建议充其量只是黑客攻击。
也就是说;假设导致悲伤的 clang-tidy
检查是 cppcoreguidelines-init-variables
规则,值得注意的是这个 仅 触发整数、布尔值、浮点数、双精度数和指针 - 和默认初始化这样一个值的成本通常可以忽略不计。除非您已对该成本进行基准测试并发现默认初始化这是一个 真正的瓶颈 ,否则几乎没有理由避免这种做法。
一般来说,初始化变量是解决这个问题最干净/最安全的方法,最终也是最佳实践无论如何。没有初始化,只需要 small f_legacy
中的错误即可导致意外的 UB。如果 f_legacy
有任何错误使得它 return 成功但忘记将值设置为 v
,那么 v
将不会被初始化并且将正式成为 UB -- 并且这只是为了保存默认初始化原语。
只是一个建议:
根据您的“最坏情况”f_wrapper
示例,NOLINT
调用调用者或必须初始化其他人的未初始化值,API 是否可以更改到 return 初始化值而不是初始化传入的内容?
如果您这样做,您可以在内部 NOLINT
它,因此需要的 NOLINT
更少,或者您自己初始化该值以防止其他潜在问题。由于该值被封装在函数中,因此这比初始化调用者的可能未初始化的值要简单得多,在我看来:
int f_wrapper() {
auto v = int{};
auto s = f_legacy(&v);
if(s != success) throw std::runtime_error{};
return v;
}