Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在“中初始化变量”;如果;陈述_C++_C++17 - Fatal编程技术网

C++ 在“中初始化变量”;如果;陈述

C++ 在“中初始化变量”;如果;陈述,c++,c++17,C++,C++17,我读到,在C++17中,我们可以在类似这样的if语句中初始化变量 if (int length = 2; length == 2) //execute something 而不是 int length = 2; if (length == 2) //do something 尽管它较短,但它会影响代码的可读性(特别是对于不知道这个新特性的人来说),我认为这对于大型软件开发来说是一种糟糕的编码实践 除了缩短代码之外,使用此功能还有其他好处吗 除了缩短代码之外,使用此功能还有其他

我读到,在C++17中,我们可以在类似这样的
if
语句中初始化变量

if (int length = 2; length == 2)
    //execute something
而不是

int length = 2;
if (length == 2)
    //do something
尽管它较短,但它会影响代码的可读性(特别是对于不知道这个新特性的人来说),我认为这对于大型软件开发来说是一种糟糕的编码实践

除了缩短代码之外,使用此功能还有其他好处吗

除了缩短代码之外,使用此功能还有其他好处吗

减少变量范围。这是有意义的,并且增加了可读性,因为它加强了您需要推理的标识符的位置。我同意应该避免使用
if
语句中的长init语句,但对于短语句,则可以

请注意,您已经可以在pre-C++17中对结果进行初始化和分支:

int *get(); // returns nullptr under some condition

if (int *ptr = get())
    doStuff();
这是符合个人观点的,但你可以认为一个明确的条件更可读:

if (int *ptr = get(); ptr != nullptr)
    doStuff();

此外,通过提及人们不习惯某个特性的事实来反对该特性的可读性是危险的。人们在某些时候还不习惯使用智能指针,但我们今天仍然一致认为(我想)它们的存在是件好事。

它将
长度的范围限制在
如果
单独使用。所以你得到了和我们当初被允许写作时一样的好处

for(int i = 0; i < ... ; ++i) {
   // ...
}

如果您的同事不知道该功能,请教他们!安抚不想学习的程序员是避免使用功能的一个糟糕借口。

if语句的新形式有很多用途

当前,初始值设定项在语句之前声明,并且 泄漏到环境作用域,或使用显式作用域。和 新的形式,这样的代码可以写得更紧凑,并且 范围控制使一些以前容易出错的构造变得有点复杂 更健壮

因此,总而言之,该语句简化了常见的代码模式,并帮助用户严格控制范围


我希望有帮助

为了最小化变量的范围,有一种习惯用法,它仅在资源在创建时有效时才定义资源(例如文件流对象):

有时,您希望能够反转该测试的逻辑,使失败成为主子句,使有效资源成为
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";
}
命名变量也可以在
中重复使用。例如:

if (double distance = std::sqrt(a * a + b * b); distance < 0.5){
    std::cerr << distance << " is too small\n";
}
if(双距离=std::sqrt(a*a+b*b);距离<0.5){

这是现有功能的扩展,有助于提高我的可读性

if (auto* ptr = get_something()) {
}
在这里,我们都创建了变量
ptr
,并对其进行非空测试。
ptr
的范围仅限于它有效的地方。让自己相信
ptr
的所有使用都是有效的要容易得多

但是,如果我们谈论的东西不能以这种方式转换为bool呢

if (auto itr = find(bob)) {
}
这不起作用。但有了这个新功能,我们可以:

if (auto itr = find(bob); itr != end()) {
}
添加一个子句,说明“此初始化何时有效”

本质上,这给了我们一组表示“初始化某个表达式,当它有效时,执行一些代码。当它无效时,放弃它”的标记


自从C++98以来,指针测试技巧一直是惯用的方法。一旦你接受了这一点,这个扩展就很自然了。

除了范围之外?我想几年前有人说过“我在C++11中读到过,我们可以创建这样的lambda语句(…),即使它更短,也会影响代码的可读性(特别是对于那些不了解这个新特性的人来说),我认为这对于大型软件开发来说是一个糟糕的编码实践。”我要说它的长度完全相同,而不是更短。纯粹的观点,因此没有答案:
if(int length=2;length==2)
可能会让你第一次看到它时感到惊讶,但它并不是一件你无法理解的复杂事情,所以第二次看到它时,它就不再是一件令人惊讶的事了,在它所属的范围内声明内容是提高可读性的主要因素之一。我想你的前提是错的;)担心那些不知道代码编写语言的人的代码可读性(这就是“不知道这个新特性”的意思)这是一场倒数第二的竞赛。你能清楚地说明你引用的是提案中的内容吗?特别是第二段。我建议使用块引号。谢谢@StoryTeller,是的,我引用了C++17中包含的OpenSTD提案中的第二段。你可以使用
if(auto p=get())
既然定义了运算符bool,我就抓住最后一句话,把它贴在一张两米长的海报上。此外,短寿命(严格限定范围)变量应该可以减少bug,因为一旦变量的用途得到满足,您以后就不能在代码中意外重用它。或者使用弱指针:
if(auto p=ptr.lock();p&&p->foo())条(*p)允许编译器在更多情况下重用堆栈空间(例如,如果您通过引用或指向外部函数的指针传递i),更好的问题可能是“与
{int i=2;If(i==2){…}
(注意附加范围)相比,这有什么好处。”我意识到这是主观的,但我更喜欢你的“粗略”版本,而不是带有if初始值设定项的版本。我发现它更容易阅读和理解。@FabioTurati我想这是因为你非常熟悉它,而另一个版本是新的。但随着时间的推移,我希望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()) {
}
if (auto itr = find(bob)) {
}
if (auto itr = find(bob); itr != end()) {
}