首页 > 解决方案 > 为什么来自匿名对象的 std::pair 会复制该对象而不是移动?

问题描述

我试着std::pair用这种风格制作:

#include <iostream>

struct A {
    A() noexcept {
        std::cout << "Created\n";
    }
    A(const A&) noexcept {
        std::cout << "Copy\n";
    }
    A(A&&) noexcept {
        std::cout << "Move\n";
    }
};

int main() {
    std::pair<A, A> a{ {},{} };
    return 0;
}

并得到这样的输出:

Created
Created
Copy
Copy

代替

Created 
Created
Move
Move

但是如果我定义我的匿名对象类型(例如std::pair<A, A> a{A{}, A{}})或使用std::make_pair<A, A>({}, {})我得到正确的结果。

std::pair构造函数必须使用std::forward<U1>andstd::forward<U2>来初始化对象,因此我认为我的对使用了错误的构造函数。为什么?

标签: c++stlstd-pair

解决方案


std::pair如何定义有问题。我什至会说这是标准中的一个小缺陷。

它有两个可以在这里使用的构造函数:

  1. pair(const T1 &x, const T2 &y);, 其中T1,T2是 的模板参数pair

  2. template <class U1, class U2> pair(U1 &&x, U2 &&y);

如果你这样做std::pair<A, A> a{A{}, A{}});,那么第二个构造函数被选中并且一切都很好。

但是如果你这样做std::pair<A, A> a{{}, {}};了,编译器就不能使用第二个构造函数,因为它不能推断U1, U2,因为{}它本身没有类型。所以使用第一个构造函数,你得到一个副本。

为了让它正常工作,std::pair应该有一个额外的非模板构造函数pair(T1 &&, T2 &&),并且为了更好地衡量两个额外的构造函数:pair(const T1 &, T2 &&)pair(T1 &&, const T2 &).


推荐阅读