gpt4 book ai didi

c++ - 将 C 代码移植到 C++,将 void* 从 malloc 转换为所需指针的问题

转载 作者:行者123 更新时间:2023-12-01 13:51:37 25 4
gpt4 key购买 nike

我目前正在将我编写的一些 C 代码移植到 C++ 中以获得乐趣。我正在努力解决 malloc()我用 C 打的电话,用 hw为简单起见是常量,但后来与运行时常量交换:

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];
}
};

最佳答案

移植不仅仅是让它一行一行地工作,所以:
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 矩阵,查找版本更快,但对于两个较小的矩阵,naive 版本更快。您需要使用与您将使用的大小接近的大小进行比较,并检查不同的编译器。在更改编译器时,我有时会遇到完全相反的“赢家”。
由于您不介意从 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

关于c++ - 将 C 代码移植到 C++,将 void* 从 malloc 转换为所需指针的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58122125/

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