使用2个Overloaded []运算符时添加了额外的[]运算符

发布于 2025-02-12 12:03:03 字数 1584 浏览 1 评论 0原文

作为一个附带项目,我正在编写几个课程,以在线性系统上进行矩阵操作和操作。类线性系统将指针保存到矩阵 std :: map中的类对象。 矩阵类本身将2D数组(“矩阵”)保存在双浮子指针中。我写了2个超载[]运算符,一个是直接从linearsystem对象返回矩阵对象的指针,另一个是从矩阵对象返回行(float *)。

这两个操作员都可以独自工作。我可以使用线性系统[“ KeyString”]从地图获取矩阵对象指针。我可以使用矩阵[row]获取行(float *)和矩阵[row] [col]从矩阵获取特定的float元素对象的2D数组。

当我把它们放在一起时,麻烦就到了。我有限的理解(上升的高级Compsci专业)告诉我,使用线性系统[“ KeyString”] [row] [col]以从线性系统中的特定数组中获取一个元素,我应该没有问题。返回类型看起来像线性系统 - > matrix- float * - > float。但是由于某种原因,只有在我在重载密钥运算符之后放置一个额外的[0]时才有效,因此呼叫看起来像这样:linearsystem [“键串”] [0] [0] [row] [col] [col] [col]。而且它必须是0,其他任何东西,我segfault。

要注意的另一个有趣的事情是,Clion看到[“ KeyString”]作为Overloaded和[row],但> [0],而不是好像它叫标准索引运营商,但在什么问题上让我感到困惑。线性系统[“ KeyString”]肯定是返回matrix *,只有一个过载[] operator。请参阅所附的屏幕快照。

ScreenShot

这是代码,让我知道是否需要更多。

线性系统[]和MAP声明:

Matrix *myNameSpace::LinearSystem::operator[](const std::string &name) {
        return matrices[name];
}

std::map<std::string, Matrix *> matrices;

矩阵[]和数组声明:

inline float *myNameSpace::Matrix::operator[](const int row) {
        return elements[row];
}
float **elements;

请注意,上述功能是内联的,因为我挑战了自己以使代码尽可能快,即使使用编译器优化,超载[]为15%比使用matrix.elements [row]慢30%。

请让我知道是否需要更多信息,这是我的第一篇文章,所以我敢肯定它不是完美的。

谢谢你!

As a side project I'm writing a couple of classes to do matrix operations and operations on linear systems. The class LinearSystem holds pointers to Matrix class objects in a std::map. The Matrix class itself holds the 2d array ("matrix") in a double float pointer. To I wrote 2 overloaded [ ] operators, one to return a pointer to a matrix object directly from the LinearSystem object, and another to return a row (float *) from a matrix object.

Both of these operators work perfectly on their own. I'm able to use LinearSystem["keyString"] to get a matrix object pointer from the map. And I'm able to use Matrix[row] to get a row (float *) and Matrix[row][col] to get a specific float element from a matrix objects' 2d array.

The trouble comes when I put them together. My limited understanding (rising senior CompSci major) tells me that I should have no problem using LinearSystem["keyString"][row][col] to get an element from a specific array within the Linear system object. The return types should look like LinearSystem->Matrix->float *->float. But for some reason it only works when I place an extra [0] after the overloaded key operator so the call looks like this: LinearSystem["keyString"][0][row][col]. And it HAS to be 0, anything else and I segfault.

Another interesting thing to note is that CLion sees ["keyString"] as overloaded and [row] as overloaded, but not [0], as if its calling the standard index operator, but on what is the question that has me puzzled. LinearSystem["keyString"] is for sure returning Matrix * which only has an overloaded [ ] operator. See the attached screenshot.

screenshot

Here's the code, let me know if more is needed.

LinearSystem [ ] and map declaration:

Matrix *myNameSpace::LinearSystem::operator[](const std::string &name) {
        return matrices[name];
}

std::map<std::string, Matrix *> matrices;

Matrix [ ] and array declaration:

inline float *myNameSpace::Matrix::operator[](const int row) {
        return elements[row];
}
float **elements;

Note, the above function is inline'd because I'm challenging myself to make the code as fast as possible and even with compiler optimizations, the overloaded [ ] was 15% to 30% slower than using Matrix.elements[row].

Please let me know if any more info is needed, this is my first post so it I'm sure its not perfect.

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乜一 2025-02-19 12:03:03

您正在用C ++编写C。您不需要那样做。它增加了复杂性。那些您一直在类型之后放置的明星。这些是原始的指针,几乎应该避免它们。 线性系统[“ foo”]矩阵*,即指向matrix的指针。它是不是 a 矩阵。和指针索引作为数组,因此linearsystem [“ foo”] [0]获取matrix*的第一个元素,将其视为数组。由于实际上只有一个元素,所以这可以解决,并且似乎可以做您想要的。如果这听起来令人困惑,那是因为。

确保您了解所有权语义。原始指针被皱眉,因为它们没有传达任何信息。如果您希望一个值由数据结构拥有,则应直接是t(或std :: simolor_ptr&lt; t&gt;(如果您需要虚拟继承),不是t*。如果您要进行函数参数或返回 想要通过所有权的值,则应使用/返回const t&amp;t&amp;如果您需要修改指南。

我不确定您的数据是什么样子,但是矩阵类的合理表示(如果您要速度速度)是类型std :: vector&lt的实例变量; double&gt;std :: vectordouble的托管数组。您可以将阵列预先放置为所需的任何尺寸,并随时随地更改它。它还可以使用三/五/五个规则

我不确定要表示的线性系统是什么,但是我将假设矩阵本来是由线性系统拥有的(即当系统为当系统时释放,矩阵也应该释放它们的内存),所以我

std::map<std::string, Matrix> matrices;

再次查看类似的东西,您可以在std :: std :: simolor_ptr中包装矩阵(如果您计划)从中继承并做动态调度。尽管我可能会质疑您的设计选择,如果您的矩阵类旨在将其分类。

没有理由Matrix :: Operator []将原始指针返回float(实际上,“原始指针到float”是一种毫无意义的类型)。我可能建议有两个过载。

float myNameSpace::Matrix::operator[](int row) const;
float& myNameSpace::Matrix::operator[](int row);

同样,线性系统:: operator []可以具有两个过载:一个常数和一个可变的。

const Matrix& myNameSpace::LinearSystem::operator[](const std::string& name) const;
Matrix& myNameSpace::LinearSystem::operator[](const std::string& name);

参考(t&amp;,而不是t*)很聪明,并且在需要时有效地解释,因此您可以调用matrix :: operator []矩阵&amp;上,而您不能在不确认间接层的情况下在矩阵*上调用该>。

那里有一个不好的C ++建议的 lot 。如果您要学习的书 /视频 /老师告诉您到处分配float ** < / code>,那么这是一本不好的书 /视频 /老师。 C ++ - 托管数据将易于错误,并且与原始指针相当(C ++编译器在优化方面都比您或我更聪明,所以让它做它的事情)。

如果您确实发现自己确实感到需要进行低级并分配到各处的原始指针,那么切换到C。C是一种专为低级指针操纵而设计的语言。 C ++是一种高级托管的内存语言;碰巧的是,出于历史原因,C ++在整个标准中偶尔放置了几百个C型分配形式的脚枪。

总结:现代C ++几乎从不使用t*newdelete。开始对智能指针感到满意(std :: unique_ptrstd :: shared_ptr)和参考。稍后您会感谢自己。

You're writing C in C++. You need to not do that. It adds complexity. Those stars you keep putting after your types. Those are raw pointers, and they should almost always be avoided. linearSystem["foo"] is a Matrix*, i.e. a pointer to Matrix. It is not a Matrix. And pointers index as arrays, so linearSystem["foo"][0] gets the first element of the Matrix*, treating it as an array. Since there's actually only one element, this works out and seems to do what you want. If that sounds confusing, that's because it is.

Make sure you understand ownership semantics. Raw pointers are frowned upon because they don't convey any information. If you want a value to be owned by the data structure, it should be a T directly (or a std::unique_ptr<T> if you need virtual inheritance), not a T*. If you're taking a function argument or returning a value that you don't want to pass ownership of, you should take/return a const T&, or T& if you need to modify the referent.

I'm not sure exactly what your data looks like, but a reasonable representation of a Matrix class (if you're going for speed) is as an instance variable of type std::vector<double>. std::vector is a managed array of double. You can preallocate the array to whatever size you want and change it whenever you want. It also plays nice with Rule of Three/Five.

I'm not sure what LinearSystem is meant to represent, but I'm going to assume the matrices are meant to be owned by the linear system (i.e. when the system is freed, the matrices should have their memory freed as well), so I'm looking at something like

std::map<std::string, Matrix> matrices;

Again, you can wrap Matrix in a std::unique_ptr if you plan to inherit from it and do dynamic dispatch. Though I might question your design choices if your Matrix class is intended to be subclassed.

There's no reason for Matrix::operator[] to return a raw pointer to float (in fact, "raw pointer to float" is a pretty pointless type to begin with). I might suggest having two overloads.

float myNameSpace::Matrix::operator[](int row) const;
float& myNameSpace::Matrix::operator[](int row);

Likewise, LinearSystem::operator[] can have two overloads: one constant and one mutable.

const Matrix& myNameSpace::LinearSystem::operator[](const std::string& name) const;
Matrix& myNameSpace::LinearSystem::operator[](const std::string& name);

References (T& as opposed to T*) are smart and will effectively dereference when needed, so you can call Matrix::operator[] on a Matrix&, whereas you can't call that on a Matrix* without acknowledging the layer of indirection.

There's a lot of bad C++ advice out there. If the book / video / teacher you're learning from is telling you to allocate float** everywhere, then it's a bad book / video / teacher. C++-managed data is going to be far less error-prone and will perform comparably to raw pointers (the C++ compiler is smarter than either you or I when it comes to optimization, so let it do its thing).

If you do find yourself really feeling the need to go low-level and allocate raw pointers everywhere, then switch to C. C is a language designed for low-level pointer manipulation. C++ is a higher-level managed-memory language; it just so happens that, for historical reasons, C++ has several hundred footguns in the form of C-style allocations placed sporadically throughout the standard.

In summary: Modern C++ almost never uses T*, new, or delete. Start getting comfortable with smart pointers (std::unique_ptr and std::shared_ptr) and references. You'll thank yourself later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文