为什么std::pair在赋值中调用显式构造函数
Why std::pair calls explicit constructors in assignment
考虑以下代码:
#include<iostream>
#include<utility>
struct Base
{
int baseint;
};
struct Der1 : Base
{
int der1int;
Der1() : der1int(1) {}
explicit Der1(const Base& a) : Base(a), der1int(1)
{
std::cerr << "cc1" << std::endl;
}
};
struct Der2 : Base
{
int der2int;
Der2() : der2int(2) {}
explicit Der2(const Base& a) : Base(a), der2int(2)
{
std::cerr << "cc2" << std::endl;
}
};
template <typename T, typename U>
struct MyPair
{
T first;
U second;
};
int main()
{
Der1 d1;
Der2 d2;
std::pair<Der1, int> p1;
std::pair<Der2, int> p2;
p1 = p2; // This compiles successfully
MyPair<Der1, int> mp1;
MyPair<Der2, int> mp2;
mp1 = mp2; // This will raise compiler error, as expected.
}
在GCC 4.5.2下测试
原因在于std::pair
来源:
/** There is also a templated copy ctor for the @c pair class itself. */
template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p)
: first(__p.first),
second(__p.second) { }
该行为是否符合c++标准?乍一看,它似乎不一致,违反直觉。STL的其他实现以同样的方式工作吗?
我不确定我理解这个问题,但基本上你是在问为什么两个不相关的std::pair
可以隐式转换,即使实例化类型不是隐式转换。这就是为什么实例化类型的隐式可转换属性不会传播到对。
标准没有为std::pair
模板提供显式赋值操作符,这意味着它将使用隐式生成的赋值操作符。为了能够赋值可转换类型对,它依赖于一个模板化的构造函数,该构造函数允许从std::pair<A,B>
到std::pair<C,D>
的隐式转换,其行为在§20.2.2 [lib.pairs]/4
template<class U, class V> pair(const pair<U, V> &p);
效果:从实参的相应成员初始化成员,执行隐式con-
标准似乎只要求实现使用隐式转换,在这个特定的实现中,转换实际上是显式的,这似乎与标准的措辞相矛盾。
std::pair类的构造函数
template<class T1, T2>
class pair
{
public:
template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p)
: first(__p.first),
second(__p.second)
{ }
};
不是复制构造函数,而是将任意pair<_U1, _U2>
转换为pair<T1, T2>
的构造函数。这适用于first
和second
成员可转换为另一对对应成员的情况。
按标准分别转换各成员
这应该是一个注释,但我希望有一些空间来输入。
那么,假设我们有两种类型:
typedef std::pair<A,B> pairAB;
typedef std::pair<S,T> pairST;
现在我想把一个赋值给另一个:
pairAB x;
pairST w;
x = w; // how?
由于std::pair
没有显式赋值操作符,因此只能使用默认赋值pairAB & operator=(const pairAB &)
。因此,调用隐式转换构造函数,相当于:
x = pairAB(w); // this happens when we say "x = w;"
然而,前面已经指出,该转换构造函数调用显式成员构造函数:pairAB(const pairST & other) : first(other.first), second(other.second) { }
快速回答:因为标准说它应该。
你的下一个问题当然是:为什么标准这么说?
想象这一行,我认为你应该同意它的工作:
std::pair<long, long> x = std::make_pair(3, 5);
但是由于3
和5
是整型,我们试图将std::pair<int, int>
赋值给std::pair<long, long>
。如果没有模板化的构造函数和模板化的赋值操作符,它将失败,正如您的MyPair
所证明的那样。
那么回答你的问题:模板化构造函数是为了方便。每个人都希望能够将int赋值给long类型。因此,将一对int型赋值给一对long型是合理的。
- 在c++中使用向量时,如何调用构造函数和析构函数
- C++:考虑但不调用构造函数的特殊性
- 对象实例化调用构造函数的次数太多
- 我使用向量来创建类对象列表.初始化向量时如何使用参数调用构造函数?
- C ++:通过大括号调用构造函数?
- 不能调用构造函数
- 赋值 boost::intrusive_ptr 而不调用构造函数?
- 在模板化类的构造函数中调用构造函数
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 为什么从另一个构造函数内部调用C++构造函数不修改类变量?
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 我不明白在这个例子中什么时候调用构造函数
- 调用c++构造函数的不同方法
- 调用构造函数与将内联常量定义为默认参数
- 如何通过 Rust FFI 调用C++构造函数?
- "new"运算符是否总是调用构造函数?
- 无法调用构造函数
- 使用 "()" 调用构造函数不同于"{}"
- 确定是调用构造函数还是强制转换运算符的因素