为什么使用声明不会继承移动构造函数
Why is the move constructor not inhereted by using declaration
在以下代码中,尽管基类是可构造的,但显然未生成派生类的移动构造函数。
#include <cstddef>
#include <memory>
#include <cstring>
#include <cassert>
template <typename T>
class unique_array : public std::unique_ptr<T[],void (*)(void*)>
{ size_t Size;
protected:
typedef std::unique_ptr<T[],void (*)(void*)> base;
unique_array(T* ptr, size_t size, void (*deleter)(void*)) noexcept : base(ptr, deleter), Size(size) {}
public:
constexpr unique_array() noexcept : base(NULL, operator delete[]), Size(0) {}
explicit unique_array(size_t size) : base(new T[size], operator delete[]), Size(size) {}
unique_array(unique_array<T>&& r) : base(move(r)), Size(r.Size) { r.Size = 0; }
void reset(size_t size = 0) { base::reset(size ? new T[size] : NULL); Size = size; }
void swap(unique_array<T>&& other) noexcept { base::swap(other); std::swap(Size, other.Size); }
size_t size() const noexcept { return Size; }
T* begin() const noexcept { return base::get(); }
T* end() const noexcept { return begin() + Size; }
T& operator[](size_t i) const { assert(i < Size); return base::operator[](i); }
unique_array<T> slice(size_t start, size_t count) const noexcept
{ assert(start + count <= Size); return unique_array<T>(begin() + start, count, [](void*){}); }
};
template <typename T>
class unique_num_array : public unique_array<T>
{ static_assert(std::is_arithmetic<T>::value, "T must be arithmetic");
public:
using unique_array<T>::unique_array;
unique_num_array(unique_num_array<T>&& r) : unique_array<T>(move(r)) {}
unique_num_array<T> slice(size_t start, size_t count) const noexcept
{ assert(start + count <= this->size()); return unique_num_array<T>(this->begin() + start, count, [](void*){}); }
public: // math operations
void clear() const { std::memset(this->begin(), 0, this->size() * sizeof(T)); }
const unique_num_array<T>& operator =(const unique_num_array<T>& r) const { assert(this->size() == r.size()); memcpy(this->begin(), r.begin(), this->size() * sizeof(T)); return *this; }
const unique_num_array<T>& operator +=(const unique_num_array<T>& r) const;
// ...
};
int main()
{ // works
unique_array<int> array1(7);
unique_array<int> part1 = array1.slice(1,3);
// does not work
unique_num_array<int> array2(7);
unique_num_array<int> part2 = array2.slice(1,3);
// test for default constructor
unique_num_array<int> array3;
return 0;
}
使用上述代码我会遇到错误(GCC 4.8.4):
test6.cpp:在函数'int main()'中:test6.cpp:47:48:错误:使用:使用 已删除函数‘unique_num_array :: simolor_num_array(const unique_num_Array&amp;)’suoliday_num_array part2 = array2.slice(1,3);
派生类中的切片函数无法按值返回,因为移动构造函数缺少。所有其他构造函数似乎都按预期工作(此示例不涵盖)。
如果我明确定义了移动构造函数(未点击行)示例编译。但是在这种情况下,默认构造函数消失了,当然不是打算。
这里发生了什么?我不明白这两种情况。
为什么在第一种情况下删除了移动构造函数?
为什么在第二种情况下会删除默认构造函数?其他人似乎可以生存。
为什么在第一种情况下删除了移动构造函数?
由于unique_num_array<T>
中有一个用户指定的副本分配运算符,因此编译器隐含地声明了构造函数。[class.copy.ctor]/8的标准说
如果类X类的定义没有明确声明移动构造函数,则在
时,将隐式地将一个不明显的人声明为违约
x没有用户指定的复制构造函数,
X没有用户指定复制分配操作员,
x没有用户宣布的移动分配运算符,
x没有用户指定的破坏者。
为什么在第二种情况下默认构造函数下降?
由于unique_num_array<T>
中有一个用户指定的移动构造函数,因此编译器暗中声明没有默认的构造函数。[class.ctor]/4的标准说
...如果没有用于X类的用户编写构造函数,则隐式声明为默认的非启示构造函数([dcl.fct.def])。/blockquote>
此外,由于保证了复制责任,该代码将在C 17之后使用。详细说明,在C 17之前,两个上下文的语义
的语义return unique_num_array<T>(...);
和
unique_num_array<int> part2 = array2.slice(1,3);
需要一个副本/移动操作,而在C 17之后,语义成为目标对象是由Prvalue Initializer初始化的,而无需实现临时性,因此无需复制/移动。
在这里有两组规则:
-
[...]所有不是默认构造函数或复制/移动构造函数且其签名与派生类中的用户定义的构造函数不匹配的默认构造函数或副本/移动构造函数
[...]在派生的类中。
-
现在自动生成非显而易见的构造仪的规则应用(如XSKXSR已经提到)。
如果类X类的定义没有明确声明移动构造函数,则如果 [...] X没有用户指定的复制分配运算符
[...] 如果没有用于X类的用户解放构造函数,则隐式称为默认值的非解释构造函数被隐式声明为默认值([dcl.fct.def])。
- 继承函数的重载解析
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 继承期间显示未知行为的子类
- 头文件-继承c++
- 在继承层次结构中复制和移动
- C++中移动赋值运算符的继承
- C++ 默认构造函数在移动和复制构造函数存在时不随"using"继承
- 如何在从模板类继承时应用移动语义
- 使用 "using" 关键字继承基类的复制和移动构造函数
- CRTP 和复制/移动赋值/构造函数继承
- 为什么使用声明不会继承移动构造函数
- 从C++中的基类继承复制/移动构造函数作为构造函数
- 如何使用继承(抽象基类)实现移动构造函数和移动赋值运算符
- 复制、移动、交换、赋值和析构函数的C++继承?我需要哪个
- 移动构造函数和多重继承
- 未调用/继承子类中的移动赋值运算符
- 继承和删除复制和移动构造函数
- 移动构造函数和继承
- 在继承层次结构中移动构造函数