优化变量值的重复分配

时间:2016-08-08 22:51:43

标签: c++ performance variables repeat compound-assignment

为了学习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,因为之前的操作会修改值。

有办法绕过这个吗?或者是否有更有效的方法来实现相同的输出? (我很感谢代码示例)

4 个答案:

答案 0 :(得分:2)

你可以用宏做这样的事情:

#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>,您会看到宏(以及任何包含)已展开。

答案 1 :(得分:2)

首先,没有特别的理由让您的变量命名为b05b06,所以让我们使用a和{{1} ,它看起来不那么难看。

从根本上说,您希望复制一对值(两个整数,b49),并将副本传递给将更改它们的代码。

最简单的解决方案是创建2个额外变量,为其分配值:

13

然后每次要使用它们时,都可以复制作业:

int a0 = 49, b0 = 13;

这将避免重复常量(您只需指定a = a0; b = b0; 49一次),但是您仍然需要复制复制变量的运算符。

任何进一步的改进都不会让你避免这个副本,它仍然必须在每个操作之前完成,但你可以通过一些技巧避免一些源代码重复:

(1)使用struct。这将允许您将两个值封装在一个:

13

现在你只重复一个命令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; ... 而不是两个。

(2)使用值参数:

p = p0

虽然没有明确指定a和b,但每次都会出现副本:来自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; } 的实际参数ab被复制到函数的形式参数变量中,巧合地也命名了maina

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

b

代码仅提到参数替换一次(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; } 行),但它在一个循环中,因此它将有效地执行所有9次。虽然代码看起来更清晰,更紧凑,但没有效率提升:您仍然可以在每次测试之前复制这两个值。

虽然可以进行一项优化:您可以为第二个参数使用共享const值,因为它永远不会被修改:

oi.op(49, 13)

然后不要通过const int b = 13; ,只需使用b

注意:请原谅我的错别字。我没有编译器方便,所以我无法验证此代码。它可能有轻微的错误。如果您找到它们,请留下评论,我会更新我的帖子。

答案 2 :(得分:1)

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

#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未经修改。

答案 3 :(得分:0)

也许你可以做这样的功能:

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%正确但它应该给你的想法&amp;原则是合理的。当然,它不适用于原始类型。