我正在设计一些用于动态数组的类(类似于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


希望对您有所帮助。

07-24 15:05