- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当我注意到以下问题时,我正在做一些 C++ 练习。给定的代码将不会在 Visual Studio 2013 或 Qt Creator 5.4.1 中运行/编译
报错:
invalid types 'double[int]' for array subscript
test[0][0] = 2;
^
然而,当您第一次更改头文件中的第 16(和 17)行时double &operator[];
到 double operator[]
并在源文件中进行相同的更改 -> 然后编译它(同时出现多个错误) -> 最后更改它回到原来的 double &operator[];
。然后在 Qt Creator 5.4.1 中它将编译并运行,同时给出预期的结果。
编辑:这并不总是有效,但是将其更改为 double *operator[]
而不是 double operator[]
总是会重现问题。
为什么会这样?
矩阵.h
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
using namespace std;
class Matrix
{
private:
double** m_elements;
int m_rows;
int m_columns;
public:
Matrix(int rows = 1, int columns = 1);
double &operator[](int index);
const double &operator[](int index) const;
friend ostream &operator<<(ostream &ostr, Matrix matrix);
};
#endif // MATRIX_H
矩阵.cpp
#include "matrix.h"
Matrix::Matrix(int rows, int columns)
{
m_rows = rows;
m_columns = columns;
m_elements = new double*[rows];
for(int i=0; i<rows; i++)
{
m_elements[i] = new double[columns];
for(int j=0; j<columns; j++)
m_elements[i][j] = 0;
}
}
double &Matrix::operator[](int index)
{
return *(m_elements[index]);
}
const double &Matrix::operator[](int index) const
{
return *(m_elements[index]);
}
ostream &operator<<(ostream &ostr, Matrix matrix)
{
for(int i=0; i<matrix.m_rows; i++)
{
for(int j=0; j<matrix.m_columns; j++)
{
ostr << matrix.m_elements[i][j] << " ";
}
ostr << "\n";
}
return ostr;
}
主要
#include <iostream>
#include "matrix.h"
using namespace std;
int main()
{
Matrix test(4,4);
test[0][0] = 2;
cout << test;
return 0;
}
最佳答案
double &Matrix::operator[](int index)
{
return *(m_elements[index]);
}
将返回对列中第一个元素的引用,而不是该列。因此调用 test[0][0] = 2;
尝试将 []
运算符应用于 double ,而不是 double 数组。
快速解决方案:
double * & Matrix::operator[](size_t index)
{
return m_elements[index];
}
这会返回对指针的引用(请继续阅读以了解我为何为该引用烦恼),您可以在返回的指针上使用 [] 来获取数据元素。
有更好的方法可以做到这一点。
如果可能,使用 std::vector 而不是动态数组。
std::vector<std::vector<double> > m_elements(m_rows, std::vector<double>(m_columns, 0.0));
这将解决很多潜在的问题,并一次性将矩阵初始化为 0。它不会解决 [][] 索引虽然。这仍然需要一些工作。
进行索引的最简单和最安全的方法是根本不使用 [] 运算符。而是定义一个新方法。通过这种方式,您可以完全控制公开的内容,并且可以在超出范围之前完全测试输入的有效性。
double &Matrix::at(size_t row, size_t column)
{
// optional overrun defence if desired
if (row < m_rows || column < m_columns)
{
return m_elements[row][column];
}
throw std::out_of_range("Matrix indices out of range");
}
double Matrix::at(size_t row, size_t column) const
{
// put overrun defence here if desired
return m_elements[row][column];
}
matrix.at(2,3) = 2;
constmatrix.at(2,3) = 2; // bad lvalue compiler error
请注意使用 size_t
代替 int
。 size_t 是无符号的,因此无需对负数进行有效性检查。不能有负数数组索引,那为什么要允许这种可能性呢?
同样值得注意的是,这种方法可以很容易地将矩阵的存储定义为一维数组,如下所示:
std::vector<double> m_elements(m_rows * m_columns, 0.0);
或者如果你必须使用数组
double m_elements = new double[m_rows* m_columns];
并像这样访问它:
double &Matrix::at(size_t row, size_t column)
{
return m_elements[row * m_rows + column];
}
为什么?有很多很好的理由。比 m_rows +1 更容易创建、维护和清理一个对象,这对我来说是一个足够好的理由。另一个极好的原因是地方。整个矩阵保证在一个连续的 block 中,而不是这里一个数组,那里另一个数组,还有一个在 RAM 中,相当于马里亚纳海沟底部。缓存命中率(以及性能)大幅提升。
如果您更喜欢数组的外观和感觉,operator() 重载非常接近。
double &Matrix::operator()(size_t row, size_t column)
{
return m_elements[row][column];
}
double Matrix::operator()(size_t row, size_t column) const
{
return m_elements[row][column];
}
matrix(2,3) = 2;
[] 运算符的建议形式返回对索引数据的引用,在本例中为 vector 或指向行数组的指针。
std::vector<double> & Matrix::operator[](size_t index)
{
return m_elements[index];
}
或
double * & Matrix::operator[](size_t index)
数组和 vector 的内部结构是相同的。
警告:这允许用户使用返回的 vector 或指针引用来解决各种问题。以 matrix[0].clear();
或 matrix[0] = NULL;
为例。
double * Matrix::operator[](size_t index)
将通过返回指针的拷贝来防止大多数滥用。不幸的是,这不能保护 vector ,因为 vector 的拷贝将是与源内容拷贝完全不同的 vector 。更新它并期望持久性是徒劳的。 vector 必须在包装类中对用户隐藏,而这很快就会成为太多的工作。
此外,返回拷贝或包装器也会阻止引用的合法使用并违反最小惊奇法则:Matrix [] 运算符与其他 [] 运算符的工作方式不同,如果出现以下情况,可能会导致意外行为毫无戒心的编码人员将其用作常规 [] 运算符。
我的意见是返回未 protected 引用,如果使用 Matrix 类的人想朝自己的脑袋开枪......好吧,你只能做这么多。如果您必须保护用户,请使用上述 at
方法或 operator()
方法。
Const[] 运算符对于 vector 是类似的
std::vector<double> const & Matrix::operator[](size_t index) const
但数组不同,因为指针和指向的值都应该是 const
double const * const & Matrix::operator[](size_t index) const
我建议的实现方式:
矩阵.h
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <vector>
// note that the using namespace std; is gone. One should never put it in the header
// and one should also think hard about putting it in the implementation file
class Matrix
{
private:
std::vector<double> m_elements;
size_t m_rows;
size_t m_columns;
public:
Matrix(int rows = 1, int columns = 1);
double &operator()(size_t row, size_t column);
double operator()(size_t row, size_t column) const;
friend std::ostream &operator<<(std::ostream &ostr, const Matrix & matrix);
};
#endif // MATRIX_H
矩阵.cpp
#include <stdexcept>
#include "Matrix.h"
Matrix::Matrix(int rows, int columns):
m_elements(rows * columns, 0.0),
m_rows(rows),
m_columns(columns)
{
}
std::ostream &operator<<(std::ostream &ostr, const Matrix &matrix)
{
for(size_t i=0; i<matrix.m_rows; i++)
{
for(size_t j=0; j<matrix.m_columns; j++)
{
ostr << matrix(i,j) << " ";
}
ostr << std::endl;
}
return ostr;
}
double &Matrix::operator()(size_t row, size_t column)
{
if (row < m_rows && column < m_columns)
{
return m_elements[row * m_rows + column];
}
throw std::out_of_range("Matrix indices out of range");
}
double Matrix::operator()(size_t row, size_t column) const
{
if (row < m_rows && column < m_columns)
{
return m_elements[row * m_rows + column];
}
throw std::out_of_range("Matrix indices out of range");
}
关于c++ 相同的代码从不在 Visual Studio 中编译/运行,有时在 Qt Creator 中编译/运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32036345/
我正在尝试将 Parcelable 数据从一个 Intent 传递到另一个 Intent ,这是我得到的错误: 08-31 14:12:22.709: E/AndroidRuntime(9931):
我收到错误消息“Parcelable 协议(protocol)需要一个在类上名为 CREATOR 的 Parcelable.Creator 对象......”,但我确实有一个 Creator,但我不知
我喜欢 Qt Creator 中的深色“FakeVim”配色方案。然而,它只会使编辑器部分变暗,而其他一切都保持正常,这有点令人不安。有没有办法让 Qt Creator 全局使用这种黑暗方案? Vim
Qt Creator 中是否可以有构建后事件(如在 VC++ 中)?特别是,我想在构建可执行文件后将其复制到另一个文件夹。可以吗? 最佳答案 添加执行脚本以复制文件作为构建步骤,如下所示, 关于qt-
有没有办法在 Qt Creator 中获取打开文档的列表。 有时当 Qt Creator 崩溃并且在重新打开时无法恢复 session 时,在它崩溃之前有一个打开的文件列表会很方便。 最佳答案 不确定
Qt 似乎不像其他 IDE 通常那样在文件夹中构建文件,例如 netbeans 将头文件放在头文件夹中,将源文件放在源文件夹中等等。我已经看到这是在 Qt 中完成的,但我不知道为什么它不在我的电脑上。
我正在尝试创建一个 2 的上标,以显示用户在我的对话框中提供的字段之后的单位标签的平方。我在 Windows 上使用 Qt Creator v2.0.1。 QLabel 有一个文本字段和一个 text
我正在尝试更改 QT Creator 中的构建输出目录(即,我想输出到 ../../bin/debug 而不是输出到 ./debug)。我尝试通过项目模式编辑构建输出目录,但它是只读的。查看 .pro
如何在 QT Creator 中仅编译项目中的一个文件。 有快捷键吗? 例如,在 VS 中,您可以按 Ctrl F7 并编译当前的 cpp 文件。 最佳答案 现在可以做到这一点,至少是 Qt Crea
使用 Qt Creator 的 Memcheck 功能返回以下内容: valgrind: Bad option: --xml=yes, but no XML destination specified
我通常使用带有 cmake 的 Qt creator 来编程 C++ 项目。最近我读了很多关于介子的书,它很简单,我喜欢测试它。 This示例解释了如何设置介子。 在使用介子时,我仍然喜欢使用 Qt
我刚刚在我的机器上构建并安装了 QtQuick3D。我运行示例项目“立方体”。 它有效,我可以构建和执行它。它向我展示了一个可以用鼠标旋转的立方体。但是在 QML 编辑器中,我在所有 Viewport
作为一名已转向 Linux 的老 Borland C++ Bulder 程序员,我很高兴找到 QT 和 QT Creator。 但是我遇到了第一个障碍:我设计了一个带有一些控件的表单,并添加了一个菜单
Visual Assist X 为 Visual Studio 提供了一个很好的功能,称为 column indicator 。它在文本编辑器中的指定列上显示一条垂直线(我使用第 80 列)。这可以帮
这看起来应该很简单,但似乎没有一种方法可以像人们期望的那样做到这一点。 我在 qt Creator 中打开了两个单独的 C++ 项目,我想针对另一个项目中的一个项目进行包含/编译。 这是我的布局: p
问题: Qt Creator 是用 Qt Creator 构建的吗? 同样,Qt Designer 是用 Qt Designer 构建的吗? 顺便说一句,为什么有两个 Qt IDE?他们是竞争对手吗?
我坐在带有 Qt Creator v2.7 的 Ubuntu 12.04(也尝试过新版本,2.8 测试版)中,当我创建一个非 Qt 项目/普通 C++ 项目(CMake Build)时,一切似乎都很好
这个问题在这里已经有了答案: 10年前关闭。 Possible Duplicate: How to get Qt Creator to work with CDB? 我正在尝试将 Cdb 与 Qt C
Qt Creator 通常将注释着色为绿色,但我在 Qt 示例中看到了蓝色注释,而且 Qt Creator 似乎将所有以 //! 开头的注释着色为蓝色。 这是一个示例屏幕截图: 这是某种约定吗?蓝色代
我刚刚从英语下载站点http://qt.nokia.com/downloads上,在我的英语Windows 7系统上下载并安装了Qt Creator 1.3.1,显然,尽管帮助文件是英语,但Qt Cr
我是一名优秀的程序员,十分优秀!