为什么来自匿名对象的 std::pair 复制该对象而不是移动?
Why is std::pair from anonymous object copying that object instead of moving?
我试着用这种风格制作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>
和 std::forward<U2>
来初始化对象,因此我认为我的一对使用了错误的构造函数。为什么?
std::pair
的定义有问题。我什至会说这是标准中的一个小缺陷。
它有两个可以在这里使用的构造函数:
pair(const T1 &x, const T2 &y);
,其中 T1
、T2
是 pair
.
的模板参数
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
应该有一个额外的 non-template 构造函数 pair(T1 &&, T2 &&)
,并且最好有两个额外的构造函数:pair(const T1 &, T2 &&)
和 pair(T1 &&, const T2 &)
.
我试着用这种风格制作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>
和 std::forward<U2>
来初始化对象,因此我认为我的一对使用了错误的构造函数。为什么?
std::pair
的定义有问题。我什至会说这是标准中的一个小缺陷。
它有两个可以在这里使用的构造函数:
的模板参数pair(const T1 &x, const T2 &y);
,其中T1
、T2
是pair
.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
应该有一个额外的 non-template 构造函数 pair(T1 &&, T2 &&)
,并且最好有两个额外的构造函数:pair(const T1 &, T2 &&)
和 pair(T1 &&, const T2 &)
.