草庐IT

c++ - 重载 operator[] 从 1 开始和性能开销

coder 2024-01-31 原文

我正在做一些 C++ 计算力学(不用担心,这里不需要物理知识),有些事情真的让我很困扰。

假设我想表示一个 3D 数学 vector (与 std::vector 无关):

class Vector {
    public:
        Vector(double x=0., double y=0., double z=0.) { 
            coordinates[0] = x;
            coordinates[1] = y;
            coordinates[2] = z;
        }
    private:
        double coordinates[3];
};

到目前为止一切顺利。现在我可以重载 operator[] 来提取坐标:

double& Vector::operator[](int i) {
     return coordinates[i] ;
}

所以我可以输入:

Vector V; 

… //complex computation with V

double x1 = V[0];
V[1] = coord2;

问题是,从 0 开始索引在这里是不自然的。我的意思是,在对数组进行排序时,我不介意,但事实是每篇论文、书籍或任何其他内容中的常规符号总是从 1 开始对坐标进行减除。 这似乎是一个狡辩,但事实是,在公式中,总是需要仔细考虑才能理解我们正在做的事情。当然,这对于矩阵来说要糟糕得多。

一个明显的解决方案只是稍微不同的重载:

double& Vector::operator[](int i) {
     return coordinates[i-1] ;
}

所以我可以打字

double x1 = V[1];
V[2] = coord2;

它看起来很完美,除了一件事:这个 i-1 减法似乎是一个很好的小开销候选者。你会说非常小,但我从事的是计算力学,所以这通常是我们负担不起的。

那么现在(最后)我的问题是:你认为编译器可以优化它,还是有办法让它优化? (模板、宏、指针或引用困惑...)

逻辑上,在

double xi = V[i];

大多数时候括号之间的整数是文字(3 次迭代 for 循环除外),内联 operator[] 应该使它成为可能,对吗?

(抱歉这个问题)

编辑:

感谢您的所有评论和回答

我有点不同意人们告诉我我们习惯于 0 索引 vector 。 从面向对象的角度来看,我看不出数学 Vector 是 0 索引的,因为它是用 0 索引数组实现的。我们不应该关心底层实现。现在,假设我不关心性能并使用映射来实现 Vector 类。然后我会发现将“1”映射到“第一个”坐标很自然。

也就是说,我尝试使用 1 索引的 vector 和矩阵,在编写一些代码之后,我发现每次使用数组时它都不能很好地交互。我以为 Vector 和容器 (std::array,std::vector...) 不会经常交互(意思是,在彼此之间传输数据),但看来我错了。

现在我有一个我认为争议较小的解决方案(请给我你的意见): 每次我在某些物理环境中使用 Vector 时,我都会想到使用枚举:

enum Coord {
    x = 0,
    y = 1,
    z = 2
};
Vector V;
V[x] = 1;

我看到的唯一缺点是这些 x、y 和 z 可以在没有警告的情况下重新定义...

最佳答案

这个应该通过反汇编来测量或验证,但我的猜测是:getter 函数很小,它的参数是常量。编译器很有可能会内联函数并常量折叠减法。在这种情况下,运行时成本将为零。

关于c++ - 重载 operator[] 从 1 开始和性能开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11855036/

有关c++ - 重载 operator[] 从 1 开始和性能开销的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  3. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  4. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  5. ruby-on-rails - ruby 范围 : operators in case statement - 2

    我想检查my_number是否在某个范围内,包括较高的值。在IF语句中我会简单地使用“x>100&&x但是我应该在Ruby案例中做什么(开关)?使用:casemy_numberwhenmy_number不起作用。备注:标准范围不包括my_number恰好为500的情况,并且我不想添加第二个“when”,因为我必须编写双重内容casemy_number#between100and500when100..500puts"Correct,dosomething"when500puts"Correct,dosomethingagain"end 最佳答案

  6. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  7. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  8. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  9. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  10. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

随机推荐