Phi*_*p-P 4 c++ pointers type-conversion void-pointers
我目前正在移植一些我写给C ++的C代码以供娱乐。我有挣扎malloc()呼叫我在做C,与h和w是为简单起见常数,但后来随着运行时间的常数交换:
double (*g2)[h][w] = malloc(h * w * sizeof(double));
Run Code Online (Sandbox Code Playgroud)
在C语言中,这是A的隐式转换void*,而C ++当然不会实现。
我已经尝试使用进行强制转换reinterpret_cast<double[h][w]>,但这仍然是无效的强制转换。
我想知道如何才能用C ++进行这项工作,因为这可以节省很多工作?
作为替代,我可能会使用带间接的矩阵类:
struct Matrix : std::vector<double> {
unsigned matSize;
std::vector<double*> indirection;
Matrix() : matSize(0) {}
Matrix(unsigned n) : matSize(n) {
resize(n*n);
indirection.resize(n);
for(unsigned i = 0; i < n; ++i) {
indirection[i] = &(*this)[i*n];
}
}
double& operator()(unsigned i, unsigned j) {
return indirection[i][j];
}
const double& operator()(unsigned i, unsigned j) const {
return indirection[i][j];
}
};
Run Code Online (Sandbox Code Playgroud)
移植不仅需要逐行地使其工作,所以:
C:
double (*g2)[h][w] = malloc(h * w * sizeof(double));
...
g2[y][x] = ...;
Run Code Online (Sandbox Code Playgroud)
C ++:
std::vector<double> g2(h*w);
...
g2[y+x*h] = ...; // or
g2[y*w+x] = ...;
Run Code Online (Sandbox Code Playgroud)
使用该语法访问元素非常方便,因此您可能希望将其包装在一个简单的类中。例:
#include <iostream>
#include <iterator>
#include <vector>
class arr2d {
public:
arr2d(size_t h, size_t w) : data_(h * w), w_(w) {}
inline double& operator()(size_t y, size_t x) {
return data_[y * w_ + x];
}
inline double operator()(size_t y, size_t x) const {
return data_[y * w_ + x];
}
// getting pointer to a row
inline double* operator[](size_t y) {
return &data_[y * w_];
}
inline double const* operator[](size_t y) const {
return &data_[y * w_];
}
inline size_t width() const { return w_; }
private:
std::vector<double> data_;
size_t w_;
};
int main() {
arr2d g2(3, 4);
g2(2, 3) = 3.14159;
// alternative access:
g2[1][2] = 1.23456;
std::cout << g2[2][3] << "\n";
double* row = g2[2];
std::copy(row, row + g2.width(), std::ostream_iterator<double>(std::cout, ", "));
std::cout << "\n";
}
Run Code Online (Sandbox Code Playgroud)
输出:
3.14159
0, 0, 0, 3.14159,
Run Code Online (Sandbox Code Playgroud)
非初始化版本可能如下所示:
class arr2d {
public:
arr2d(size_t h, size_t w) : data_(new double[w * h]), w_(w) {}
inline double& operator()(size_t y, size_t x) { return data_[y * w_ + x]; }
inline double operator()(size_t y, size_t x) const { return data_[y * w_ + x]; }
inline double* operator[](size_t y) { return &data_[y * w_]; }
inline double const* operator[](size_t y) const { return &data_[y * w_]; }
inline size_t width() const { return w_; }
private:
std::unique_ptr<double[]> data_;
size_t w_;
};
Run Code Online (Sandbox Code Playgroud)
但是请注意,
std::copy(row, row + g2.width(), std::ostream_iterator<double>(std::cout, ", "));
第一个示例中的会导致未定义的行为。
另请注意,此版本将删除复制构造函数和复制分配运算符。如果需要,则必须自己实施。
非初始化版本的创建时间当然很难与任何初始化版本相提并论,但是对于访问时间,人们可能会认为查找表或您所谓的间接表,因为与之相比,行会加快处理速度一路相乘和加法。
我的结果:
8x8 http : //quick-bench.com/f8zcnU9P8oKwMUwLRXYKZnLtcLM
1024x1024 http://quick-bench.com/0B2rQeUkl-WoqGeG-iS1hdP4ah8
4096x4096 http://quick-bench.com/c_pGFmB2C9_B3r3aRl7
它似乎有所不同。对于4096x4096矩阵,查找版本速度更快,但是对于两个较小的矩阵,原始版本的查找速度更快。您需要比较使用的大小接近将要使用的大小,并还要检查不同的编译器。更改编译器时,有时我会遇到完全相反的“赢家”。
由于您不介意从std::vector查询表继承或保留额外的数据,因此可以选择。它似乎略胜于其他版本。
class arr2d : protected std::vector<double*> {
public:
using std::vector<double*>::operator[]; // "row" accessor from base class
arr2d(size_t h, size_t w) :
std::vector<double*>(h),
data_(new double[w * h]),
w_(w),
h_(h)
{
for(size_t y = 0; y < h; ++y)
(*this)[y] = &data_[y * w];
}
inline size_t width() const { return w_; }
inline size_t height() const { return h_; }
private:
std::unique_ptr<double[]> data_;
size_t w_, h_;
};
Run Code Online (Sandbox Code Playgroud)
以下是Philipp-P(OP:s)自己针对不同2D阵列实现的测量结果:
8x8 http://quick-bench.com/vMS6a9F_KrUf97acWltjV5CFhLY
1024x1024 http://quick-bench.com/A8a2UKyHaiGMCrf3uranwOCwmkA
4096x4096 http://quick-bench.com/XmYQc0kAUWU23V3Go0Lucioi_Rg
相同版本的5点模板代码的结果:
8x8 http : //quick-bench.com/in_ZQTbbhur0I4mu-NIquT4c0ew
1024x1024 http://quick-bench.com/tULLumHZeCmC0HUSfED2K4nEGG8
4096x4096 http://quick-bench.com/_MRNRZ03Favx91-5QIXx
| 归档时间: |
|
| 查看次数: |
231 次 |
| 最近记录: |