gpt4 book ai didi

c++ - 避免 C++ 循环中复杂对象的最小范围效率低下的技术?

转载 作者:IT老高 更新时间:2023-10-28 22:22:18 25 4
gpt4 key购买 nike

问题第一

在 C++ 中是否有一种优雅的解决方案来避免为了提高效率而必须声明仅在循环外的循环内使用的复杂对象变量?

详细说明

一位同事提出了一个有趣的观点。到我们的代码政策,该政策规定(释义):始终为变量使用最小范围并在第一次初始化时声明变量

编码指南示例:

// [A] DO THIS
void f() {
...
for (int i=0; i!=n; ++i) {
const double x = calculate_x(i);
set_squares(i, x*x);
}
...
}

// [B] DON'T do this:
void f() {
int i;
int n;
double x;
...
for (i=0; i!=n; ++i) {
x = calculate_x(i);
set_squares(i, x*x);
}
...
}

这一切都很好,这当然没有错,直到您从原始类型转移到对象。 (对于某种界面)

例子:

// [C]
void fs() {
...
for (int i=0; i!=n; ++i) {
string s;
get_text(i, s); // void get_text(int, string&);
to_lower(s);
set_lower_text(i, s);
}
...
}

这里,字符串 s 将被销毁,它在每个循环周期释放内存,然后每个循环 get_text 函数都必须为 s 缓冲区重新分配内存。

这样写显然更有效率:

  // [D]
string s;
for (int i=0; i!=n; ++i) {
get_text(i, s); // void get_text(int, string&);
to_lower(s);
set_lower_text(i, s);
}

因为现在 s 缓冲区中分配的内存将在循环运行之间保留,我们很可能会节省分配。

免责声明: 请注意:由于这是循环并且我们正在谈论内存分配,我确实认为它为时过早优化 来考虑这个问题。当然,有些情况和循环的开销并不重要。但是 n 具有比开发人员最初期望的更大的唠叨倾向,并且代码具有在性能确实很重要的上下文中运行的唠叨倾向。

无论如何,现在“通用”循环构造的更有效方法是违反代码局部性并声明复杂对象不合适,“以防万一”。这让我相当不安。

请注意,我考虑这样写:

// [E]
void fs() {
...
{
string s;
for (int i=0; i!=n; ++i) {
get_text(i, s); // void get_text(int, string&);
to_lower(s);
set_lower_text(i, s);
}
}
...
}

没有解决方案,因为可读性受到更大影响!

进一步考虑,无论如何,get_text 函数的接口(interface)是非惯用的,因为输出参数是 so 反正昨天和“好"接口(interface)将按值返回:

  // [F]
for (int i=0; i!=n; ++i) {
string s = get_text(i); // string get_text(int);
to_lower(s);
set_lower_text(i, s);
}

这里,我们不为内存分配支付双倍,因为极有可能s会通过RVO从返回值构造,所以对于[F]我们支付与 [C] 中相同的分配开销 [C] 情况不同,我们无法优化此接口(interface)变体。

所以底线似乎是使用最小范围(可能)会损害性能并使用干净的接口(interface)我至少认为按值返回比out-ref-param更干净东西 会阻止优化机会——至少在一般情况下是这样。

问题并不是为了效率而不得不放弃干净的代码,问题是一旦开发人员开始发现这种特殊情况,整个编码指南(参见[A], [B]) 失去权威。

问题现在是:见第一段

最佳答案

It would be clearly more efficient to write: [start of example D ...]

我怀疑这一点。您要为从循环外开始的默认构造付费。在循环中,有可能 get_text 调用重新分配缓冲区(取决于您的 get_textstring 的定义方式)。请注意,对于某些运行,您实际上可能会看到改进(例如,在字符串逐渐变短的情况下),而对于某些运行(每次迭代时字符串长度增加约 2 倍),性能会受到巨大影响。

如果不变量构成瓶颈(分析器会告诉您),将不变量从循环中提升出来是非常有意义的。否则,请使用惯用的代码。

关于c++ - 避免 C++ 循环中复杂对象的最小范围效率低下的技术?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10769289/

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