我读到在C ++17中,我们可以像这样在if
语句中初始化变量
if (int length = 2; length == 2)
//execute something
不是
int length = 2;
if (length == 2)
//do something
即使它更短,它也会影响代码的可读性(尤其是对于不了解这个新特性的人),我认为这是大型软件开发中的一种不良编码实践。
除了使代码更短之外,使用这个特性还有什么优点吗?
它将length
的作用域限制在if
中。因此,您将获得与最初允许编写时相同的好处。
for(int i = 0; i < ... ; ++i) {
// ...
}
不是变量泄漏
int i;
for(i = 0; i < ... ; ++i) {
// ...
}
短暂的变量因为多种原因而更好。但是举几个例子:
if(std::lock_guard _(mtx); guarded_thing.is_ready()) {
}
如果你的同事不知道这个功能,那就教给他们吧!迁就不愿意学习的程序员,是避免使用功能的借口。 if (auto p = ptr.lock(); p && p->foo()) bar(*p);
- Deduplicator{int i = 2; if (i == 2) {...}}
,这有什么优势?”(注意额外的作用域。) - TLW使用这个特性还有什么优势吗,除了让代码更短?
它可以缩小变量的作用域。这确实很有意义,并提高了可读性,因为它增强了你需要考虑的标识符的局部性。我同意要避免在 if
语句内部使用长的初始化语句,但对于短的内容,这是可以的。
注意,在 C++17 之前,您已经可以对结果进行初始化和分支:
int *get(); // returns nullptr under some condition
if (int *ptr = get())
doStuff();
这取决于个人观点,但你可以认为明确的条件更易读:
if (int *ptr = get(); ptr != nullptr)
doStuff();
此外,通过指出人们不习惯某个功能来反驳其可读性是危险的。有一段时间人们也不习惯使用智能指针,但我们今天都会认同(我猜)它们的好处。
if (auto p = get())
。 - sudo rm -rf slashif(auto file = std::ifstream("filename"))
{
// use file here
}
else
{
// complain about errors here
}
// The identifier `file` does not pollute the wider scope
有时您希望能够颠倒测试逻辑,使失败成为主要子句,而有效资源则成为else
子句。以前这是不可能的。但现在我们可以这样做:
有时您想要能够颠倒该测试的逻辑,使失败成为主要子句,而有效资源成为else
子句。以前不可能做到这一点。但现在我们可以这样做:
if(auto file = std::ifstream("filename"); !file)
{
// complain about errors here
}
else
{
// use file here
}
一个例子可能是抛出异常:
if(auto file = std::ifstream(filename); !file)
throw std::runtime_error(std::strerror(errno));
else
{
// use file here
}
有些人喜欢编写代码,让函数在出现错误时尽早停止执行,否则继续执行。这种习惯将停止执行的逻辑放在继续执行的逻辑之前,一些人可能觉得这更加自然。
它在逻辑事件方面特别有用。考虑下面这个例子:
char op = '-';
if (op != '-' && op != '+' && op != '*' && op != '/') {
std::cerr << "bad stuff\n";
}
看起来有点粗糙。除非您非常熟悉否定的OR,AND逻辑,否则您可能需要停下来思考这种逻辑,这通常是很差的设计。使用if初始化可以增加表达力。
char op = '-';
if (bool op_valid = (op == '-') || (op == '+') || (op == '*') || (op == '/'); !op_valid) {
std::cerr << "bad stuff\n";
}
命名的变量也可以在 if
语句内重复使用。例如:
if (double distance = std::sqrt(a * a + b * b); distance < 0.5){
std::cerr << distance << " is too small\n";
}
这很棒,特别是考虑到变量是有作用域的,因此之后不会污染空间。
这是现有功能的扩展,据我体验它有助于阅读。
if (auto* ptr = get_something()) {
}
在这里,我们创建变量ptr
并测试其非空。 ptr
的范围仅限于其有效的范围内。让所有使用ptr
都是有效的要容易得多。
但是,如果我们谈论的内容不以这种方式转换为 bool
呢?
if (auto itr = find(bob)) {
}
那不起作用。但是有了这个新功能,我们可以:
if (auto itr = find(bob); itr != end()) {
}
if (int length = 2; length == 2)
可能第一次看到会让你感到惊讶,但这并不是什么复杂的东西,第二次就不会太惊讶了,并且将声明的内容放在其所属的范围内是提高可读性的主要因素之一。在我看来,你的前提是错误的 ;)” - 463035818_is_not_a_number