【问题标题】:What implementation of Swap() function is better and for what situations? [closed]Swap() 函数的哪种实现更好,在什么情况下更好? [关闭]
【发布时间】:2013-01-23 04:32:55
【问题描述】:

我定义了两个函数:

1).

template<class T> inline
void swap(T &first, T &second)
{   
    if (&first != &second)
    {
        T tmp = first;
        first = second;
        second = tmp;
    }
}

2).

template<typename T>
inline void SwapMe(T *first, T *second)
{
    if(*first != *second)
    {
        T tmp = *first;
        *first = *second;
        *second = tmp;
    }
}

哪个实现更好(第一个等于 std::swap() )?

【问题讨论】:

  • 它们的语义有些不同。
  • 还有不同的要求。第二个需要operator!=(T,T),或者兼容的东西。
  • 因为这是 C++,你应该只使用std::swap&lt;t&gt;,尤其是因为在 C++11 中它将使用移动语义。
  • 您可能在SwapMe 中指的是if (first != second)。或者如果不是,那么您可能在swap 中表示if (first != second)。目前swap 比较地址,而SwapMe 比较指向的对象的值。这种差异与函数是采用引用参数还是指针参数无关。

标签: c++ templates stl std swap


【解决方案1】:

第一个版本更好地使用通过引用传递或通过值传递的变量。

第二个更适合指向值的指针。

它们是不同的,因为引用是不同于指针的动物。

【讨论】:

  • 对于内存管理...我记得,对于指针内存分配 4 个字节的缓冲区(指针精确定位的位置),对于引用没有额外的内存分配。除了模板之外,第二个更适用于纯 C。
  • @OlegOrlov:至于内存管理,你仍然只是在堆栈上分配一个类型T;因此,对于这两个示例,内存管理在这里都不是问题。
  • T - 只是编译器粘贴所需类型的提示。它不是 C# 中的泛型类型。所以它不仅仅是 T,而是 T* 和任何指针都等于 void* ( 4 bytes ),如果你明确使用它,内存将为指针分配一些大小。
【解决方案2】:

除了第一个之外,两者都不是更好,因为我更喜欢它。其他人会更喜欢第二种,因为他们认为应该在调用者端明确说明函数可能会修改其参数。我的想法是,如果您不知道函数的作用,则不应调用它们,并且它们的作用应该从它们的名称中显而易见,就像交换一样。我还认为,C++ 中原始指针的唯一目的是作为非拥有、可重新定位和/或可空引用。除非您必须实现自己的内存管理类,例如标准库中的类。

【讨论】:

    【解决方案3】:

    没有人说案例 2 是危险的。如果您的代码将包含 NULL 指针,您是否会收到程序崩溃:SwapMe (NULL, NULL)

    【讨论】:

    • 您只会捕获:错误 C2974:'SwapMe':'T' 的模板参数无效,应键入。如果你使用 SwapMe(NULL, NULL);或错误 C2784: 'void SwapMe(T *,T *)' : 如果使用 SwapMe(NULL, NULL) 如果使用 MSC++,则无法从 'int' 推断出 'T *' 的模板参数
    • 我的意思是如果真正的指针为空,这段代码就有问题
    • 它甚至无法根据您的建议进行编译
    【解决方案4】:

    有一个标准函数模板大约与您的swap(即std::swap)相同,并且有一个标准函数模板大约与您的SwapMe 相同(即std::iter_swap)。

    两者都不是真的“更好”,它们各有各的用途。它们中的任何一个都可以使用另一个来实现,但是正如在标准中发生的那样,iter_swap 是根据swap 定义的,因此swap 被认为是更基本的操作。 swap 您将为自己的类型进行 ADL 重载。

    在您的代码中,SwapMe 中的 *first != *second 测试非常可疑。它需要T 才能拥有operator!=,并且考虑到!= 对于某些类型可能会很慢,所以这并不是什么优化,因此它会为常见情况增加显着成本(当对象不相等时) .此外,根据T 类型的定义,交换相等的对象可能会产生影响(例如,在vector 的情况下,容量不参与相等比较,但它 当您使用std::swapvector::swap 进行交换时会被 交换)。所以目前SwapMe 更糟,但我怀疑这不是故意的:-)

    事实上,swap 函数中的任何此类测试都是可疑的,因为它往往会减慢常见情况,即使只是微小的。但是,如果您使测试相同,那么它们是否应该存在是与参数类型应该是什么不同的参数。

    【讨论】:

      猜你喜欢
      • 2016-03-21
      • 2017-11-04
      • 2019-09-26
      • 2012-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多