gpt4 book ai didi

c++ - 指针运算 : out of bound without dereferencing

转载 作者:搜寻专家 更新时间:2023-10-30 23:56:56 25 4
gpt4 key购买 nike

我想知道以下代码是否不被 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 实现相同的设计,其中 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(使用断言对其进行检查)并向我的 Array2D 对象添加一行。你可以这样做:

Array2D<double> A(0, 10);
Array1D<double> B(10);

// work with B
A.push_back(B);

该代码在 clang、g++ 和 icpc 上运行良好,但我仍然想知道它是否有效。 C++11 标准的第 5.7 节是关于这个问题的,但讨论的是“数组对象”。我想知道我的 p 是否指向他们所谓的“数组对象”,或者数组对象是否是诸如“double p[5]”之类的东西。

最佳答案

这是未定义的行为。实际上,它可能适用于大多数现代系统,但过去曾有系统会导致程序崩溃。指针只是一种特殊类型的整数;它可以有各种结构,只是将指向未映射内存的指针加载到寄存器中可能会导致陷阱。

来自标准(添加了重点),§5.7/5:

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i + n-th and i − n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

最后一句话很重要:“否则,行为未定义”。

关于c++ - 指针运算 : out of bound without dereferencing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26626663/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com