【发布时间】:2016-10-22 10:41:33
【问题描述】:
我有一些令我感到困惑的代码。特别是,当我尝试将某些内容作为初始化列表添加到列表中时——它会一直工作,直到我添加一个析构函数——然后它开始尝试找到一个复制构造函数。
这似乎不是完全一致的行为。举个最小的例子:
#include <list>
int main()
{
class MemberType
{
public:
MemberType() {}
MemberType(MemberType&& copy) { }
};
struct ListItemType
{
MemberType x;
~ListItemType() {}
};
std::list<ListItemType> myList;
myList.push_back({MemberType()});
return 0;
}
这在 GCC 和 VS2015 中编译失败,因为 push_back 尝试访问 ListItemType 复制构造函数:
main()::ListItemType::ListItemType(const main()::ListItemType&)
(根据我的理解)。这似乎是有道理的,因为列表 push_back 将进行复制(因为没有移动构造函数),除非这是 不是 如果您删除析构函数的行为。注释掉析构函数,编译按预期成功。
也就是说,即使使用析构函数,以下内容也可以正常工作 - 不需要复制或移动构造函数来满足它。不过,这对我来说似乎是相同的行为。
ListItemType foo = { MemberType() };
最后,如果你删除或注释掉MemberType的移动构造函数——编译再次成功——意味着下面的代码将编译。
#include <list>
int main()
{
class MemberType
{
public:
MemberType() {}
};
struct ListItemType
{
MemberType x;
~ListItemType() {}
};
std::list<ListItemType> myList;
myList.push_back({MemberType()});
return 0;
}
有人可以解释一下这里的行为吗?为什么push_back 会尝试访问ListItemType 的复制构造函数——但前提是ListItemType 具有析构函数且MemberType 具有移动构造函数?
【问题讨论】:
-
简而言之:添加析构函数会抑制隐式移动构造函数的生成,因此复制/移动操作会退回到隐式复制构造函数