优化变量值的重复赋值

Optimizing repeating assignment of variable values

本文关键字:赋值 变量值 优化      更新时间:2023-10-16

为了学习c++中的复合赋值,我创建了以下代码来演示它们的作用:

int b05;
int b06 = 13;
b05 = 49;
b05 += b06; // b05 = b05 + b06
cout << "(+=) compound assignment: " << b05 << endl;
b05 = 49;
b05 -= b06; // b05 = b05 - b06
cout << "(-=) compound assignment: " << b05 << endl;
b05 = 49;
b05 *= b06; // b05 = b05 * b06
cout << "(*=) compound assignment: " << b05 << endl;
b05 = 49;
b05 /= b06; // b05 = b05 / b06
cout << "(/=) compound assignment: " << b05 << endl;
b05 = 49;
b05 %= b06; // b05 = b05 % b06
cout << "(%=) compound assignment: " << b05 << endl;
b05 = 49;
b05 >>= b06; // b05 = b05 >> b06
cout << "(>>=) compound assignment: " << b05 << endl;
b05 = 49;
b05 <<= b06; // b05 = b05 << b06
cout << "(<<=) compound assignment: " << b05 << endl;
b05 = 49;
b05 &= b06; // b05 = b05 & b06
cout << "(&=) compound assignment: " << b05 << endl;
b05 = 49;
b05 ^= b06; // b05 = b05 ^ b06
cout << "(^=) compound assignment: " << b05 << endl;
b05 = 49;
b05 |= b06; // b05 = b05 | b06
cout << "(|=) compound assignment: " << b05 << endl;

如您所见,我必须将49的值重新赋值给b05,因为前面的操作修改了值。

有没有办法绕过这个?还是有更有效的方法来达到同样的输出?(我希望有一个代码示例)

您可以使用宏做类似的事情:

#define compound(op) 
    b05 = 49; 
    b05 op b06; 
    std::cout << "(" << #op << ") compound assignment: " << b05 << std::endl;

然后像这样调用它:

int b05, b06 = 13;
compound(+=)
compound(/=)
// etc...

这实际上是在编译时替换文本。在您有compound(...)的每个地方,它将被替换为复合宏的文本,op将被替换为您在括号中提供的任何内容(在本例中,某种操作符)。

要查看实际操作,执行g++ -E <codefile>,您将看到宏(和任何包含)已经展开。

首先,您的变量命名为b05b06没有特别的原因,所以让我们使用ab,它看起来不那么难看。

从根本上说,你想要复制你的一对值(两个int, 4913),并将副本传递给代码来改变它们。

最简单的解决方案是创建两个额外的变量,并将您的值赋给它们:

int a0 = 49, b0 = 13;

,然后每次你想使用它们时,你可以复制赋值:

a = a0; b = b0;

这将避免重复常量(您只指定一次4913),但是您仍然需要重复复制操作符来复制变量。

任何进一步的改进都不会让您避免这种复制,它仍然必须在每个操作之前完成,但是您可以使用一些小技巧来避免一些源代码重复:

(1)这将允许您将两个值封装在一个值中:

struct params {
  int a;
  int b;
}
params p0;
p0.a = 49;
p0.b = 13;
params p;
...
p = p0;
p.a += p.b; // p.a = p.a + p.b
cout << "(+=) compound assignment: " << p.b << endl;
...

现在你只重复一个命令p = p0,而不是两个。

(2)使用值参数:
void test1(int a, int b) {
  a += b; cout << "(+=) compound assignment: " << a << endl;
}
void test2(int a, int b) {
  a -= b; cout << "(-=) compound assignment: " << a << endl;
}
...
int main() {
  int a = 49; int b = 13;
  test1(a, b);
  test2(a, b);
  ...
  return 0;
}

虽然没有显式赋值a和b,但每次仍然会发生复制:实际参数abmain被复制到函数的形式参数变量中,巧合的是也被命名为ab

(3)可以通过使用函数引用来避免重复代码。下面是一个示例,每个操作都有一个匿名函数数组:

typedef int OperationFn(int, int)
struct OperationInfo {
  std::string label;
  OperationFn op;
}
OperationInfo operations[9] = {
  { "+=", [](int a, int b) { return a += b } },
  { "-=", [](int a, int b) { return a -= b } },
  { "*=", [](int a, int b) { return a *= b } },
  { "/=", [](int a, int b) { return a /= b } },
  { "%=", [](int a, int b) { return a %= b } },
  { ">>=", [](int a, int b) { return a >>= b } },
  { "<<=", [](int a, int b) { return a <<= b } },
  { "&=", [](int a, int b) { return a &= b } },
  { "^=", [](int a, int b) { return a ^= b } },
}
int main() {
  for (int i = 0; i < 9; i++) {
    const OperationInfo& oi = operations[i];
    cout << "(" << oi.label << ") compound assignment: ";
    cout << oi.op(49, 13) << endl;
  }
  return 0;
}

代码只提到参数替换一次(oi.op(49, 13)行),但它是在循环中,因此它将有效地执行所有9次。虽然代码看起来更干净、更紧凑,但效率没有提高:在每次测试之前,您仍然要复制这两个值。

有一个优化是可能的:您可以为第二个参数使用共享的const值,因为它永远不会被修改:

const int b = 13;

然后不要传递b,只使用b

注意:请原谅我的拼写错误。我手边没有编译器,所以我无法验证这段代码。它可能有一些小错误。如果你发现了,请留下评论,我会更新我的帖子。

您误解了复合操作。它们只影响表达式的左值。

#include <iostream>
int main() {
    int b05 = 10; int b06 = 5;
    b05 |= b06;
    std::cout << "b05 " << b05 << ", b06 " << b06 << "n";
}
http://ideone.com/5nT7pR

输出:

b05 15, b06 5

b06未修改

也许你可以这样写一个函数:

class Obj
{
public:
    Obj& operator+= (const Obj &) { return *this; }
    Obj& operator-= (const Obj &) { return *this; }
};
void testFunction(std::function<Obj&(Obj *, const Obj &)> functionToTest)
{
  Object object;
  Object otherObject;
  functionToTest(&object, otherObject);
  cout << "(+=) function test: " << object << endl;
}
int main(void)
{
  std::function<Obj&(Obj *, const Obj &)> functionToTest(&Obj::operator+=);
  testFunction(functionToTest);
  std::function<Obj&(Obj *, const Obj &)> functionToTest2(&Obj::operator-=);
  testFunction(functionToTest2);
}

这段代码不是100%正确,但它应该给你一个想法&这个原则是合理的。当然,它不适用于基本类型。