gcc 意外调用已删除的移动构造函数
Unexpected invocation of deleted move constructor by gcc
我正在尝试编写一个非常简单的数组 class,其函数 returns 是其自身的一部分。展示比解释更容易...
template<typename T>
class myArrayType
{
// Constructor; the buffer pointed to by 'data' must be held
// elsewhere and remain valid for the lifetime of the object
myArrayType(int size, T* data) : n(size), p(data)
{
}
// A move constructor and assign operator wouldn't make
//much sense for this type of object:
#ifndef _MSC_VER
myArrayType(myArrayType<T> &&source) = delete;
myArrayType & operator=(myArrayType<T> &&source) && = delete;
#else
#if _MSC_VER >= 2000
myArrayType(myArrayType<T> &&source) = delete;
myArrayType & operator=(myArrayType<T> &&source) && = delete;
#endif
// Earlier versions of Visual C++ do not generate default move members
#endif
// Various whole-array operations, which is the main reason for wanting to do this:
myArrayType & operator+=(const myArrayType &anotherArray) & noexcept
{
for (int i=0; i<n; ++i) p[i] += anotherArray.p[i];
return *this;
}
// etc.
// The interesting bit: create a new myArrayType object which is
// a subsection of this one and shares the same memory buffer
myArrayType operator()(int firstelement, int lastelement) noexcept
{
myArrayType newObject;
newObject.p = &p[firstelement];
newObject.n = lastelement - firstelement + 1;
return newObject;
}
private:
T* p;
int n;
}
当然,我想做的是能够写:
double aBigBlobOfMemory[1000]; // Keep it on the stack
myArrayType<double> myArray(1000, aBigBlobOfMemory);
myArrayType<double> mySmallerArray = myArray(250, 750);
...所以 'mySmallerArray' 是一个完整的 myArrayType 对象,它包含指向 myArray 内存子集的指针。
在 Visual Studio 2013 年,这似乎可行(或至少可以编译),但在 gcc 中,它以我不理解的方式失败了。尝试创建 mySmallerArray 时的编译器错误是:
use of deleted function myArrayType(myArrayType<T> &&)
...插入符号指向行尾。换句话说,gcc 似乎认为在调用 'subarray operator' 时我实际上是在尝试调用一个移动构造函数,但我终究无法看到它想在哪里使用它,或者为什么。
我是否遗漏了一些非常明显的东西,或者任何人都可以阐明这一点吗?
gcc 正在做正确的事。
您从 operator() 返回 newObject,myArrayType 的一个实例。这必须 移动 到变量 mySmallerArray 中。这是用你没有的移动构造函数完成的。
您需要声明一个移动构造函数。
这个 class 有一个移动构造函数确实有意义 - 它可以将指针 p 从现有实例移动到新实例。
我正在尝试编写一个非常简单的数组 class,其函数 returns 是其自身的一部分。展示比解释更容易...
template<typename T>
class myArrayType
{
// Constructor; the buffer pointed to by 'data' must be held
// elsewhere and remain valid for the lifetime of the object
myArrayType(int size, T* data) : n(size), p(data)
{
}
// A move constructor and assign operator wouldn't make
//much sense for this type of object:
#ifndef _MSC_VER
myArrayType(myArrayType<T> &&source) = delete;
myArrayType & operator=(myArrayType<T> &&source) && = delete;
#else
#if _MSC_VER >= 2000
myArrayType(myArrayType<T> &&source) = delete;
myArrayType & operator=(myArrayType<T> &&source) && = delete;
#endif
// Earlier versions of Visual C++ do not generate default move members
#endif
// Various whole-array operations, which is the main reason for wanting to do this:
myArrayType & operator+=(const myArrayType &anotherArray) & noexcept
{
for (int i=0; i<n; ++i) p[i] += anotherArray.p[i];
return *this;
}
// etc.
// The interesting bit: create a new myArrayType object which is
// a subsection of this one and shares the same memory buffer
myArrayType operator()(int firstelement, int lastelement) noexcept
{
myArrayType newObject;
newObject.p = &p[firstelement];
newObject.n = lastelement - firstelement + 1;
return newObject;
}
private:
T* p;
int n;
}
当然,我想做的是能够写:
double aBigBlobOfMemory[1000]; // Keep it on the stack
myArrayType<double> myArray(1000, aBigBlobOfMemory);
myArrayType<double> mySmallerArray = myArray(250, 750);
...所以 'mySmallerArray' 是一个完整的 myArrayType 对象,它包含指向 myArray 内存子集的指针。
在 Visual Studio 2013 年,这似乎可行(或至少可以编译),但在 gcc 中,它以我不理解的方式失败了。尝试创建 mySmallerArray 时的编译器错误是:
use of deleted function myArrayType(myArrayType<T> &&)
...插入符号指向行尾。换句话说,gcc 似乎认为在调用 'subarray operator' 时我实际上是在尝试调用一个移动构造函数,但我终究无法看到它想在哪里使用它,或者为什么。
我是否遗漏了一些非常明显的东西,或者任何人都可以阐明这一点吗?
gcc 正在做正确的事。
您从 operator() 返回 newObject,myArrayType 的一个实例。这必须 移动 到变量 mySmallerArray 中。这是用你没有的移动构造函数完成的。
您需要声明一个移动构造函数。
这个 class 有一个移动构造函数确实有意义 - 它可以将指针 p 从现有实例移动到新实例。