我想知道下面的代碼是否被C++標準接受。指針算術:超出範圍而無需解除引用
int n{ 10 };
double* p = new double[0];
double* q = p + n;
std::cout << "n = " << static_cast<int>(q - p) << std::endl;
我想讓程序顯示n的值。
由於這個問題可能看起來很奇怪,下面是對這個問題起源的解釋。我想在2D中設計一個動態數組類(想想一個容器的std :: vector類型,但是用2D而不是1D)。一個簡單的方法是:
template <typename T>
class Array2D<T> {
private:
T* data_;
int nb_rows_;
int nb_columns_;
public:
...
};
不幸的是,這樣的設計是不是SIMD友好的循環如
Array2D<int> A(5, 6);
for (int i = 0; i < A.nb_rows(); ++i) {
for (int j = 0; j < A.nb_columns(); ++j) {
A(i, j) += 1;
}
}
將無法向量化,因爲編譯器不能肯定,如果nb_columns_沒有改變在循環期間由於指針混疊。因此,我使用與std :: vector的大多數實現相同的設計,其中矢量的大小在指針中「隱藏」。
template <typename T>
class Array2D<T> {
private:
T* data_;
T* nb_rows_;
T* nb_columns_;
public:
Array2D(int n, int p) {
data_ = new T[n * p];
nb_rows_ = data_ + n;
nb_columns_ = data_ + p;
}
...
int nb_columns() const {
return static_cast<int>(nb_columns_ - data_);
}
...
};
這種設計,只要工作以及N> = 1且p> = 1。但是,如果n = 0且p = 5,則最終獲得的那種「問題」解釋如上。與0行構建Array2D可能因爲在我類
void push_back(const Array1D<T>& B);
以下方法,它尺寸p的Array1D(檢查與一個assert)並增加了一個行到我Array2D對象的是有用的。你可以這樣做:
Array2D<double> A(0, 10);
Array1D<double> B(10);
// work with B
A.push_back(B);
的代碼工作正常上鐺,g ++以及ICPC但我還是想知道,如果它是有效的。 C++ 11標準的第5.7節就是關於這個問題,但討論了「數組對象」。我想知道,如果我的p指向他們所謂的「數組對象」,或者如果一個數組對象是諸如「double p [5]」之類的東西。
@Joachim Pileborg:我想確定這一點。你能引用這個標準嗎?當data_ + n可能溢出時,可能還有一些指針溢出。 – InsideLoop 2014-10-29 09:34:12
我不知道用零大小的數組會做什麼? – 2014-10-29 09:34:13
正如Ali Kazmi所說,零大小的陣列有什麼好處?難道你不能只是檢查是否n * p == 0然後就像這樣返回:'Array2D(int n,int p){if(n * p == 0)return; data_ = new T [n * p]; nb_rows_ = data_ + n; nb_columns_ = data_ + p; }' – 2014-10-29 09:36:54