我目前正在移植一些我写到C++的C代码来取乐。由于简单的原因,我在用C进行的malloc()调用中挣扎,h和w是常量,但后来与运行时常量进行了交换:
double (*g2)[h][w] = malloc(h * w * sizeof(double));在C语言中,这是一个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];
}
};发布于 2019-09-26 17:51:23
移植不仅仅是让它工作,一行行,所以:
C:
double (*g2)[h][w] = malloc(h * w * sizeof(double));
...
g2[y][x] = ...;C++:
std::vector<double> g2(h*w);
...
g2[y+x*h] = ...; // or
g2[y*w+x] = ...;使用该语法对于访问元素是不方便的,因此您可能希望将其包装在一个简单的类中。示例:
#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";
}输出:
3.14159
0, 0, 0, 3.14159,非初始化版本可能如下所示:
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_;
};但是请注意,
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_B3r3aRl7cDK6BlxU
似乎各不相同。对于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_;
};以下是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-5IXnxGNpRNwQ
发布于 2019-09-26 17:51:52
在C++中,除非有必要,否则不建议手动分配内存。让标准库和模板为您工作。
如果您想进入C++,它们可能非常有用,学习起来也很棒!这样可以节省很多时间,并编写一些更好的代码。
例如,此数据类型用于什么?如果它适合您的使用,您可以考虑使用std::array创建2D数组。
std::array<std::array<double, w>, h>
如果需要定期调整数组的大小,则可以使用std::vector。它实际上具有与数组相同的性能,因为这就是它在引擎罩下的全部性能。您可以在必要时使用reserve()或resize(),push_back使用1.5倍的增长方案,并且擅长其工作。
编辑:由于已知的大小,数组在这里可能会更好。从评论中得到建议。
发布于 2019-09-26 18:10:07
您可以这样做,这在C和C++中都可以使用:
double *g2 = (double*) malloc(h * w * sizeof(double));尽管,正如其他人所指出的,在C++中,这并不是解决这个问题的方法。例如,您应该使用std::vector来代替:
#include <vector>
std::vector<double> g2(h * w);在这两种情况下,您都会在一个连续的内存块中得到一个动态分配的2D double数组。因此,您需要使用g2[(row*w)+col]语法来访问各个元素,其中0 <= row < h和0 <= col < w。
https://stackoverflow.com/questions/58122125
复制相似问题