来自临时的 std::pair:为什么调用复制构造函数而不是移动构造函数?

phi*_*inz 3 c++ move std-pair

考虑以下代码:

#include<iostream>
using namespace std;
struct A {
    A(const A&){
        cout<<"copy constructor"<<endl;
    }
    A(A&&){
        cout<<"move constructor"<<endl;
    }
    ~A(){
        cout<<"destructor"<<endl;
    }
    static std::pair<A,int> f1()
    {
        int i = 1;
        return std::pair<A,int>{i,2};
    }
    static std::pair<A,int> f2()
    {
        int i = 1;
        return std::pair<A,int>{A(i),2};
    }
    private:
    A(int){
        cout<<"constructor"<<endl;
    }
};

int main()
{
    cout<<"f1: "<<endl;
    A::f1();
    cout<<"f2: "<<endl;
    A::f2();
}
Run Code Online (Sandbox Code Playgroud)

构造函数A(int)是私有的,因此A不能pair<A,int>从 就地构造int。因此,在 中构建了一个临时的f1。在f2我显式创建临时文件但行为不同时,输出为:

f1: 
constructor
copy constructor
destructor
destructor
f2: 
constructor
move constructor
destructor
destructor
Run Code Online (Sandbox Code Playgroud)

我希望移动构造函数也被调用,A::f1但复制构造函数被调用,这是次优的。为什么会这样呢?

Jar*_*d42 5

如果你看一下pair的构造函数

有趣的构造函数是 (2) 和 (3)

// (2)
constexpr pair( const T1& x, const T2& y );

// (3)
template< class U1 = T1, class U2 = T2 >
constexpr pair( U1&& x, U2&& y ); // SFINAE on constructible
Run Code Online (Sandbox Code Playgroud)

请注意,没有pair(T1&&, T2&&).

原来A(int)如此privatestd::is_constructible_v<A, int>就是如此false

因此f1,对于 ,只有 (2) 是可行的构造函数(因此是副本)。

对于f2,(3) 是可行的(并且匹配得更好),因此完成了前进(因此移动)。