C ++ is a range-based loop trap.

Source: Internet
Author: User

C ++ is a range-based loop trap.

The range-based loop of C ++ is a new feature of C ++ 11, which is very convenient. To some extent, it replaces the for loop usage of the iterator. However, a Range-based for loop has a hidden trap. Serious memory errors may occur if you do not pay attention to it.

Example

See the following code:

 1 #include <iostream> 2 #include <string> 3  4 using namespace std; 5  6 struct MyClass 7 { 8     string text = "MyClass"; 9 10     string& getText()11     {12         return text;13     }14 };15 16 int main()17 {18     for (auto ch : MyClass().text)19     {20         cout << ch;21     }22     cout << endl;23 }

This code is very simple, and the output result is "MyClass ". However, if you slightly modify the 18th rows, it will look like the following:

    for (auto ch : MyClass().getText())    {        cout << ch;    }

The results are not output, and the program exits directly. To understand why such behavior occurs, you must first know how the range-based for loop is defined.

Range-based for loop Definition

In the C ++ 11 standard, it has the following format:

attr(optional) for ( range_declaration : range_expression ) loop_statement

Among them, attr is optional. range_declaration is equivalent to "auto ch" in our code, and range_expression is equivalent to "MyClass (). getText () ", loop_statement is" {cout <ch ;}"

According to the standard, the above loop expression should be equivalent

{    auto && __range = range_expression;    for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {        range_declaration = *__begin;        loop_statement    }}

Begin_expr and end_expr are determined by the range_expression type.

Note that the _ range type declared in the first line is "auto &", so if range_expression is a temporary object of the right value, _ range can prolong the survival time of range_expression.

Problem Analysis

After reading the definition of the for loop in the given range, the cause of the problem in the previous example is clear.

In the original example, range_expression is "MyClass (). text", MyClass () is a temporary object, and "MyClass ()" is the right value. Therefore, the expression "MyClass (). text" is also the right value, and "MyClass (). text" is part of a temporary object. Therefore, in the "auto & _ range = range_expression;" Statement, auto is deduced as "std: string ". When the right value is referenced as a part of a temporary object, the lifetime of the entire temporary object can be extended, and the temporary object will be destroyed only when the reference is destroyed. Therefore, the for loop can be executed normally.

However, after modification, range_expression is "MyClass (). getText ()". Similarly, MyClass () is a temporary object, and the expression "MyClass ()" is the right value. However, the return type of "getText ()" is "string &". Therefore, the expression "MyClass (). getText ()" is the left value. Therefore, in the "auto & _ range = range_expression;" Statement, auto is deduced as "string &", and the statement is equivalent to "string & _ range = range_expression; ". Although "MyClass (). getText () "This object is part of a temporary object, but it does not prolong the lifetime of the temporary object when initializing a non-const left value reference, so at the end of the initialization statement, the temporary object MyClass () is destroyed, __range becomes a wild reference, so the subsequent loop statements may encounter memory errors.

Summary

The range-based for loop is very convenient, and can even traverse temporary objects, which is often used in daily life. However, if you want to traverse a temporary object, the temporary object to be traversed must be a right-value expression, note that other temporary objects generated in the expression are destroyed before the loop starts. Only the final temporary objects returned by the expression are saved.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.