【问题标题】:swap implementations: efficiency & range of applicability?交换实施:效率和适用范围?
【发布时间】:2015-03-28 01:49:37
【问题描述】:

我正在尝试涵盖所有 swapfunction 实现。

在swap函数的以下实现中,不需要临时变量来交换两个参数的值:

void swapNoTemp1(int &a, int &b){
    a = a + b;
    b = a - b;
    a = a - b; 
}

或

template <class T>
void swapNoTemp2(T& i, T& j){
    i -= j;
    j += i;  
    i = (j - i);  
}

或

void swapNoTemp3(int &a, int &b){
    a ^= b;
    b ^= a;
    a ^= b;
}

因此,就使用的内存而言,它比:

void swap(int &a, int &b){
    int temp = a;
    a = b;
    b = temp; 
}

另一方面,swap 可以使用:

void swapPointers(int *i, int *j) {
    int t = *i;
    *i = *j;
    *j = t;
}

我正在尝试比较所有现有的实现并了解它们的适用范围。

【问题讨论】:

  • 不是,不是。现在你已经取缔了大量的输入对。
  • 另请注意,当&amp;a == &amp;b 时,它甚至不适用于unsigned(没有溢出)。
  • Rewrite 使用 XOR 来避免溢出。一个不错的大评论也不会受到伤害。
  • 即使避免临时的函数工作得很好,你最好的希望是在堆栈上保存sizeof(int) 分配。我非常怀疑这是否值得担心。

标签: c++ function implementation effective-c++


【解决方案1】:

第一个函数的行为未定义。算术可能会导致溢出,并且在某些机器上,溢出会导致异常。

标准规定:

如果在计算表达式期间,结果未在数学上定义或不在 其类型的可表示值,行为是未定义的。 [注意:大多数现有的 C++ 实现 忽略整数溢出。 ... ]

虽然在实践中你很有可能该函数会起作用,但最好还是避免它。

【讨论】:

  • 这是正确的答案,因为 OP 使用有符号整数类型。可能值得注意的是,除了硬件异常之外,还有许多其他方式会被这种未定义的行为所困扰(就像 FreeBSD 的家伙 recently were),并且与签名情况不同,上溢和下溢很好 -由 [basic.fundamental]/4 为无符号整数类型定义。
  • @simplicisveritatis,如果你需要检查,在你的检查中溢出不是一个好主意。特别是因为如果它被定义为溢出,你得到的结果可能不会大于INT_MAX(它不是,如上所述)。选择的未定义行为替代方案只会让一切变得不可预测。
  • @simplicisveritatis 如果a 和b 是ints,那么a+b 也是int。所以(即使加法有效)预计总和不会超过INT_MAX :-)。
  • 如果a == INT_MAX 和b == INT_MAX,则a + b 不在int 的可表示值范围内,并且行为未定义根据[expr]/4(引用在答案中)。
  • @AlexD 我明白了,它只会溢出,并且条件总是错误的,因为总和仍然是 int 在有效范围内(与溢出无关)。
猜你喜欢
  • 2012-12-02
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多