title: C++ copy and move constructors with lambda expressions
body: <p>I've bumped into something strange with C++ copy and move constructors, here when passing to the lambda expression both the copy and move constructors get executed. Strangely though, when I change the declared type of the lambda to <code>auto</code> or use the <code>regular_test</code> function, I get the expected behaviour (copy construction only). Does anyone understand why this is? (tested with both clang and gcc, not msvc)</p>
  <pre><code>#include &lt;iostream&gt;
  #include &lt;iomanip&gt;
  #include &lt;functional&gt;
  
  using namespace std;
  
  struct Test {
      inline Test() {
          cout &lt;&lt; setw(20) &lt;&lt; &quot;constructor &quot;;
          PrintAddress();
      }
  
      Test(const Test&amp;) {
          cout &lt;&lt; setw(20) &lt;&lt; &quot;copy constructor &quot;;
          PrintAddress();
      }
  
      Test&amp; operator=(const Test&amp;) {
          cout &lt;&lt; setw(20) &lt;&lt; &quot;copy assignment &quot;;
          PrintAddress();
          return *this;
      }
  
      Test(Test&amp;&amp; other) {
          cout &lt;&lt; setw(20) &lt;&lt; &quot;move constructor &quot;;
          PrintAddress();
      }
  
      Test&amp; operator=(Test&amp;&amp;) {
          cout &lt;&lt; setw(20) &lt;&lt; &quot;move assignment &quot;;
          PrintAddress();
          return *this;
      }
  
      virtual ~Test() {
          cout &lt;&lt; setw(20) &lt;&lt; &quot;destructor &quot;;
          PrintAddress();
      }
  
      void PrintAddress() {
          cout &lt;&lt; &quot;Test&amp;: &quot; &lt;&lt; this &lt;&lt; endl;
      }
  };
  
  Test regular_test (Test t) {
      cout &lt;&lt; &quot;regular_test&quot; &lt;&lt; endl;
      return t;
  }
  
  int main() {
      cout &lt;&lt; &quot;start&quot; &lt;&lt; endl;
      function&lt;Test(Test)&gt; lambda_test = [] (Test t) {
          cout &lt;&lt; &quot;lambda_test&quot; &lt;&lt; endl;
          return t;
      };
      Test t;
      lambda_test(t);
      //regular_test(t);
      cout &lt;&lt; &quot;done&quot; &lt;&lt; endl;
      return 0;
  }
  </code></pre>
  <pre><code>start
          constructor Test&amp;: 0x7fffef6faf28
     copy constructor Test&amp;: 0x7fffef6faf08
     move constructor Test&amp;: 0x7fffef6fade8
  lambda_test
     move constructor Test&amp;: 0x7fffef6faf10
           destructor Test&amp;: 0x7fffef6fade8
           destructor Test&amp;: 0x7fffef6faf10
           destructor Test&amp;: 0x7fffef6faf08
  done
           destructor Test&amp;: 0x7fffef6faf28
  </code></pre>