我正在设计一些用于动态数组的类(类似于std :: vector)。我不想使用std :: vector的原因是因为我的C ++程序经常用作从C / C ++ / Fortran / Delphi调用的库,因此将数组输入作为指针。出于安全原因,std :: vector不能在构造时窃取指针。我的Array1D可以用作std :: vector,但也可以使用指针构造。不幸的是,Visual Studio 2013似乎担心我的设计。在提出问题之前,我需要解释一下这种设计。
这是我班的布置
template <typename T>
class Array1D {
private:
T* data_;
T* size_; // No stored as an int for optimisation purposes
bool owner_;
public:
Array1D(int n) {
data_ = new T[n];
size_ = data_ + n;
owner_ = true;
}
Array1D(T* data, int n) {
data_ = data;
size_ = data + n;
owner_ = false;
}
...
};
大多数情况下,它作为std :: vector工作,并且owner_设置为true。也可以从指针构造一个Array1D,这次owner_设置为false。在这种情况下,不允许进行某些操作(例如,调整大小)(通过断言)。数组A的复制构造函数和分配设计为:
Array1D(const Array1D&B):将B的深层副本复制到A中。构造后,A拥有其内存。
Array1D(Array1D && B):在所有情况下的移动操作。施工后,A的所有权状态与B相同。
operator =(const Array1D&B):将B的深层副本复制到A中。如果A不拥有其内存,则可以使用一个断言来检查A和B的大小是否相同。分配不会更改A的所有权状态。
operator =(Array1D && B):如果A和B拥有内存,则移动操作。否则,我们将进行深层复制,如果A不拥有其内存,则使用断言检查大小。分配不会更改A的所有权状态。
我对我的二维数组(其元素以行优先顺序存储)应用了相同的想法
template <typename T>
class Array2D {
private:
T* data_;
T* size_[2];
bool owner_;
public:
Array2D(int n, int p) {
data_ = new T[n];
size_[0] = data_ + n;
size_[1] = data_ + p;
owner_ = true;
}
Array1D(T* data, int n, int p) {
data_ = data;
size_[0] = data + n;
size_[1] = data + p;
owner_ = false;
}
...
Array1D<T> operator()(int i) {
Array1D<T> row(data_ + i * nb_columns(), nb_columns());
return row;
}
...
int nb_columns() const {
return static_cast<int>(size_[1] - data_);
}
};
由operator()(int i)返回的Array1D不拥有其内存,并且包含一个指向Array2D对象拥有的第i行的指针。在以下类型的代码中很有用
sort(Array1D<T>& A); // A function that sorts array in place
Array2D<double> matrix(5, 100); // Construct an array of 5 rows and 100 columns
... // Fill the array
sort(matrix(3)) // Sort the 4th row
二维数组行的那些“临时视图”非常有用,但我更喜欢将它们限制为临时对象以限制别名。
不幸的是,使用Visual Studio 2013,我从IDE中收到了针对行sort(matrix(3))的以下警告:“用于将r值绑定到l值引用的选项是非标准的Microsoft C ++扩展”。我知道matrix(3)是一个临时存在的对象,并且通过某种排序对其进行修改看起来很奇怪。但是,由于它是一个“视图”,因此对其进行修改会修改矩阵拥有的内存,因此很有用。
所以我的问题如下:
我在做什么有效的C ++? (修改临时值)
这种设计有缺陷吗?
PS:完整代码可在Github上找到。
最佳答案
我在做什么有效的C ++? (修改临时值)
不是。非常量左值引用不能绑定到临时对象:
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
这种设计有缺陷吗?
您正在修改包装在对象中的内容。由于您需要一个左值,因此只需通过一个中间变量即可将其固定:
auto m_temp_lvalue = matrix(3); // get the 4th row
sort(m_temp_lvalue); // sort the 4th row
希望对您有所帮助。