为什么移动构造函数和移动赋值运算符被调用而不是复制
why are move constructor and move assignment operator called and not copy?
可能的重复项:
防止非常量左值解析为右值引用而不是常量左值引用
复制构造函数和转发构造函数之间的冲突
我有这些类,我需要存储 std::unique_ptr(适应的 boost::any):
class any
{
public:
any()
: content(0)
{
}
any(any const&) = delete;
any(any && other)
: content(other.content)
{
content = 0;
}
template<typename ValueType>
any(ValueType const& value)
: content(new holder<ValueType>(value))
{
}
template<typename ValueType>
any(ValueType && value,
typename std::enable_if<!std::is_lvalue_reference<ValueType>::value,
void>::type* = 0)
: content(new holder<ValueType>(std::move(value)))
{
}
~any()
{
delete content;
}
public: // modifiers
any & swap(any & rhs)
{
std::swap(content, rhs.content);
return *this;
}
any & operator=(const any &) = delete;
any & operator=(any && rhs)
{
return swap(rhs);
}
template<typename ValueType>
any & operator=(ValueType const& rhs)
{
any(rhs).swap(*this);
return *this;
}
template<typename ValueType>
typename std::enable_if<!std::is_lvalue_reference<ValueType>::value,
any&>::type operator=(ValueType && rhs)
{
any(std::move(rhs)).swap(*this);
return *this;
}
public: // queries
bool empty() const
{
return !content;
}
const std::type_info & type() const
{
return content ? content->type() : typeid(void);
}
private: // types
class placeholder
{
public: // structors
virtual ~placeholder()
{
}
public: // queries
virtual const std::type_info & type() const = 0;
};
template<typename ValueType>
class holder : public placeholder
{
public: // structors
template <class T>
holder(T && value)
: held(std::forward<T>(value))
{
}
holder & operator=(const holder &) = delete;
public: // queries
virtual const std::type_info & type() const
{
return typeid(ValueType);
}
public:
ValueType held;
};
private: // representation
template<typename ValueType>
friend ValueType * any_cast(any *);
template<typename ValueType>
friend ValueType * unsafe_any_cast(any *);
placeholder * content;
};
而这个测试用例:
any a;
any b(a);
b = a;
而这个:
std::map<int, int> map({{1,1},{2,2}});
any b(map);
std::cout << map.size() << std::endl; // displays 0
令我惊恐的是,在 gdb 下,我注意到在构造和分配b
(甚至从 map)时调用移动构造函数和移动赋值运算符,即使我没有用 std::move
标记a
,它也不是临时的。有人可以解释为什么吗?
我的第一个答案是错误的。再次阅读您非常难以阅读的代码后,我看到您明确提供了一个移动和默认构造函数,但没有复制构造函数。如果类具有任何用户定义的构造函数(其中有两个),则编译器不会为该类生成任何其他构造函数。因此,您的类没有复制构造函数。
编辑:所以,回到我原来的答案(由您的评论提示)。 §12.8/7 [类复制] 说:
成员函数模板永远不会实例化以执行复制 类对象到其类类型的对象。 [示例:
struct S { template<typename T> S(T); template<typename T> S(T&&); S(); }; S f(); const S g; void h() { S a( f() ); // does not instantiate member template; // uses the implicitly generated move constructor S a(g); // does not instantiate the member template; // uses the implicitly generated copy constructor }
—结束示例 ]
由于您的复制构造器是成员模板,但您的移动构造函数不是,因此在此处选择后者(您的情况与该方面的示例不同)。
相关文章:
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 使lambda不可复制/不可移动
- 复制和交换习惯用法与移动操作之间的交互
- 为什么调用复制构造函数而不是移动构造函数?
- 隐式移动与复制操作和遏制
- 具有已删除移动和复制构造函数的类的就地构造
- 使用移动和复制语义时函数匹配如何工作?
- 直接初始化不可复制、不可移动的成员,而不使用聚合初始化
- 包装二进制缓冲区 - 可能没有多余的移动/复制?
- 当使用三元运算符并删除移动/复制CTOR时,Visual Studio不执行RVO
- 我们是否应该从派生类调用基类移动复制/分配构造函数
- 具有unique_ptr成员变量的 C++ 移动/复制/赋值<AbstractClass>
- 返回带有已删除移动/复制 ctor 的类型临时
- 消除默认/删除移动/复制语义中涉及的样板的好方法是什么
- C++11:移动/复制构造不明确
- 关于移动/复制c++对象实例
- 我丢失了一个移动/复制赋值
- 如何创建一个不可移动/复制构造的对象数组
- 编译器何时在C++中移动/复制