English 中文(简体)
避免C++中复杂物体在环绕中效率极低的技术?
原标题:Techniques to avoid minimal scope inefficiency with complex objects in loops in C++?

Question First

C++中是否有一种优雅的解决方案来防止人们不得不宣布复杂的物体变量,这些变量仅在循环之外循环中使用,以便提高效率?

Detailed explanation

一位同事对我们的守则政策提出了一个有趣的要点,其中指出(原措辞):“这些”总是对变量使用最小范围,并在初始化时宣布变量 < /它们>。

编码指南示例:

// [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);
  }
  ...
}

在此, 字符串将被销毁, 它会释放每个循环周期的内存, 然后每个循环的 < code> get_ text 函数将不得不为缓冲新分配内存 。

写:

  // [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);
  }

现在缓冲中分配的内存将在循环运行之间保存,我们很可能节省拨款。

disclapeer: > 请注意: 由于这是循环,我们在谈论内存分配,我确实 not 认为它具有“强度”前期优化 n 有比Dev最初预期的更大的趋势,而代码有在性能 does 重要的情况下运行的紧要趋势。

总之,现在“一般”环状结构的更有效方法是 违反代码位置 并宣布复杂的物体“以防万一 ” 。这让我很不安。

请注意,我考虑这样写:

// [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);
    }
  }
  ...
}

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

Thinks furder , get_text 函数的界面无论如何都是非多义的,因为昨天的参数是 so , 一个“好”界面会按值返回 :

  // [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);
  }

在此,我们确实不支付双倍 的记忆分配费,因为极有可能通过RVO从回报值中构建 ,因此,对于[F],我们在分配管理费时支付与[C]相同的 不同,但[C]案例无法优化这一界面变量。

因此, " 坚固 " 底线 似乎是,使用最小范围(可能)损害性能,使用清洁界面 I,至少考虑按价值回报,比那些反射参数 更清洁,将防止优化机会 -- -- 至少在一般情况下是如此。

" 强势 " 问题并不严重,有时为了提高效率,人们不得不放弃干净的守则,问题是,一旦Devs开始发现这类特殊情况,整个《编码指南》(见[A]、[B])就会失去权威。

现在的“强度”问题 < /强度”将是:见第一段。

最佳回答

一、二、三、三、三、三、三、四、四、四、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、五、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、六、

  • make an exception to the rule for these heavyweights. like D and note that you can restrict the scope as desired.
  • permit a helper function (the string could also be a parameter)
  • and if you really didn t like those, you could declare a local in your for loop s scope using a multi-element object which held your counter/iterator and the temporary. std::pair<int,std::string> would be one option, although a specialized container could reduce the syntactic noise.

(在许多情况中,外出参数将比REVO型的更快)

问题回答

写作显然更有效率:[起例D.]

我怀疑此位 。 您正在为默认构造支付费用, 要从环外开始。 在环外, 存在一种可能性, 即 < code>> get_ text 呼叫重新调配缓冲( 取决于如何定义您的 < code> get_ text 和 < code> string ) 。 请注意, 对于一些运行者来说, 这实际上可能是一个改进( 比如, 您的字符串会逐渐缩短), 而对于某些运行者来说( 字符串长度会每转动大约上升2倍), 性能会受到极大打击 。

如果出现瓶颈(一个剖面师会告诉你的 ), 就完全合理了。 否则,你应该使用普通的代码。

取决于 get_text 的执行情况。

< 坚固> 如果您可以执行它, 以便它大部分时间重新使用字符串对象中分配的空间, 然后明确声明环外对象, 以避免在每次环迭代中出现新的动态内存分配 。

动态分配非常昂贵(最佳单行分配器需要40个单项分配指令,多行分配增加间接费用,而非所有分配器都是“最佳”),并且可以分割内存。

(BTW, std::string 通常执行所谓的“小字符串优化 ”, 避免对小字符串进行动态分配。 所以, 如果您知道大部分字符串将足够小, 而执行 std::: string 将不会改变, 理论上也可以避免动态分配, 即使在每次迭代中构建新对象时。 但是, 这非常脆弱, 所以我建议不要这样做 。)


通常情况下, 它都取决于您使用它们的物体和函数是如何执行的。 如果您关心性能, 您将不得不逐案处理这些“ 禁制漏漏 ” 。 因此, 请明智地选择战斗: 先量度并优化瓶颈 。

如果您对字符串类有在文字上执行的复制件, 那么 to_ lower(s) 将会分配内存, 所以不清楚您是否只要在循环之外声明即可获得性能 。

In my opinion, there are two possibilities: 1.) You have a class whose constructor does something non-trivial which need not be re-done in each iteration. Then it is logically straightforward to put the declaration outside the loop. 2.) You have a class whose constructor does not do anything useful, then put the declaration inside the loop.

如果 1 是真实的, 那么您可能应该将对象分割成一个辅助对象, 例如, 分配空间, 并进行非三边初始化, 以及一个飞量对象 。 例如 :

StringReservedMemory m (500); /* base object for something complex, allocating 500 bytes of space */
for (...) {
   MyOptimizedStringImplementation s (m);
   ...
}




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?