Home > Blockchain >  strange std::list iteration behavior
strange std::list iteration behavior

Time:04-12

#include <list>
#include <iostream>
#include <utility>
#include <conio.h>

std::list<int>&& asd()
{ 
    std::list<int> a{ 4, 5, 6 }; 
    return std::move( a ); 
}

int main()
{
    std::list<int> a{ 1, 2, 3 };
    std::list<int> &&b = std::move( a );
    for( auto &iter : b )
        { std::cout<<iter<<' '; }
    
    std::list<int> &&c{ asd() };
    for( auto &iter : c )
        { std::cout<<iter<<' '; _getch(); }
}

this is what my program outputs:

1 2 3
4 3502376 454695192 3473720 4 3502376 454695192 3473720 4 3502376 454695192 3473720 4

CodePudding user response:

std::list<int> a{ 4, 5, 6 }; 

This object is declared locally inside this function, so it gets destroyed when the function returns.

std::list<int>&& asd()

This function returns an rvalue reference. A reference to some unspecified object.

What happens here is that this "unspecified object" gets destroyed when this function returns, so the caller ends up holding a reference to a destroyed object.

return std::move( a ); 

The dirty little secret is that std::move() does not actually move anything. It never did, it never will. All that std::move() does is cast its parameter into an rvalue reference. Whether the object gets moved, or not, requires other dominoes to fall into place. std::move() merely provides one piece of the puzzle, but all other pieces of this puzzle must exist in order for an actual move to happen.

Here, those other pieces of the puzzle do not exist. Therefore, nothing gets moved. A reference to a destroyed object gets returned, and all subsequent use of the destroyed object results in undefined behavior.

  •  Tags:  
  • c
  • Related