std::pair from temporary:为什么调用复制构造函数而不是移动构造函数?

问题描述 投票:0回答:1

考虑以下代码:

#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();
}

构造函数

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

f1: 
constructor
copy constructor
destructor
destructor
f2: 
constructor
move constructor
destructor
destructor

我希望在

A::f1
中也调用移动构造函数,但调用了次优的复制构造函数。为什么会这样?

c++ move std-pair
1个回答
3
投票

如果你看对的构造函数

有趣的构造函数是 (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

注意,没有

pair(T1&&, T2&&)
.

因为

A(int)
private
std::is_constructible_v<A, int>
false

所以对于

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

对于

f2
,(3)是可行的(并且更好的匹配),所以前进(所以移动)完成了。

© www.soinside.com 2019 - 2024. All rights reserved.