默认构造函数阻止调用emplace_back
Default constructor prevents from calling emplace_back
似乎
添加默认构造函数会阻止调用emplace_back
并产生错误消息:"静态断言失败:类型不可分配"(gcc 5.3 和 -std=c++14)。下面是说明该问题的简单代码:
class A {
public:
int a;
A() = default;
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error: type is not assignable
return 0;
}
删除默认构造函数时,错误消失了!此外,如果定义了默认构造函数(即使它不执行任何操作),则错误也会消失:
class A {
public:
int a;
A() {
}
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A b;
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error gone
return 0;
}
似乎"A() = default;"是导致问题的原因。这是编译器部分的正常行为还是错误?
这是一个
libstdc++错误(编辑:报告为错误69478)。
简而言之,libstdc++ 的std::vector
,在这里相关,使用std::uninitialized_copy
(与移动迭代器配对)在重新分配时移动元素,如果类型是微不足道的并且迭代器的引用类型是可分配的(即,概念上使用的赋值运算符是可用的),则将其减少到std::copy
)。
然后,指向平凡类型的指针(或者在我们的例子中,包装指针的move_iterator
)的std::copy
反过来又优化为对memmove
的调用以及对is_copy_assignable
的检查。当然,在这种情况下,这种检查是错误的,因为uninitialized_copy
与移动迭代器配对,只需要事物是可移动的。
或者默认构造函数是用户定义的,则类不是简单的,因此不会命中触发此 bug 的代码路径。
相关文章:
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 推导 std::vector::back() 的返回类型
- 为什么 C++ std::unordered_map 从 emplace/ 找到返回一个迭代器?
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 将 std::map::emplace 与返回 shared_ptr 的函数一起使用是否正确?
- vector.push_back(vector.back()+1) 是未定义的行为吗?
- 不为 emplace() 定义构造函数的解决方法
- 如何提取由 unordered_map::emplace 重新调整的货币对的值?
- 如何最好地将 emplace 与 std::map 一起使用
- 线路抑制状态错误 C4703 可能未初始化的局部指针变量"back"已使用
- std::vector using back(), pop_back(), push_back(), 得到'double free or corruption'错误
- std::vector::emplace() 真的在面对抛出移动构造函数/赋值运算符时提供了强大的异常保证吗?
- std::map::emplace无法解决,但插入右值有效 - 为什么?
- vector.back()和vector.end()有什么区别
- 为什么 std::map emplace 需要在 gcc 上有一个复制构造函数
- 为什么unordered_map的 emplace piecewise_construct参数需要默认构造函数?
- std::元组到元组的映射和使用 emplace
- 列表大小为 1,但 front() 和 back() 不相等
- 如何使用 emplace 添加到C++中的地图
- C++ map emplace