Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当编写自己的swap()函数/方法有性能优势时_C++_Swap - Fatal编程技术网

C++ 当编写自己的swap()函数/方法有性能优势时

C++ 当编写自己的swap()函数/方法有性能优势时,c++,swap,C++,Swap,假设我有这样一节课: struct A{ std::string a; std::string b; std::string c; std::string d; }; 如果我使用std::swap,它可能会执行以下操作: // pseudo-code: void std::swap(A &a, A &b){ A tmp = std::move(a); a = std::move(b); b = std::move(tmp); } 它将使用默认

假设我有这样一节课:

struct A{
  std::string a;
  std::string b;
  std::string c;
  std::string d;
};
如果我使用
std::swap
,它可能会执行以下操作:

// pseudo-code:
void std::swap(A &a, A &b){
   A tmp = std::move(a);
   a = std::move(b);
   b = std::move(tmp);
}
它将使用默认的c-tor构造“空”对象
tmp
——通常是廉价的操作。然后它有望移动3次,除非在疯狂的情况下移动到复制

但是,如果我自己进行交换:

void swap(A &a, A &b){
   std::swap(a.a, b.a);
   std::swap(a.b, b.b);
   std::swap(a.c, b.c);
   std::swap(a.d, b.d);
}
它肯定会使用更少的内存,但它仍然需要构造空
std::string
-4次

我可以发狂,用single
std::string
就可以了

在所有情况下,这看起来并不是很大的改善


我能想到的唯一合适的情况是,默认的c-tor是否贵得离谱。我说的对吗?

你不能说你需要或者永远不应该自己交换
,这完全取决于上下文。在您的示例中,它很可能是不必要的,但类的逻辑可能更复杂

假设您有一个类,它持有指向某个数据结构的指针,并且有许多与该结构相关联的度量,每个度量都需要很长的时间来计算,并且需要大量的空间来存储,这些度量在对数据进行某些计算时用作临时度量(我知道下面的例子可能是一个设计糟糕的类,但它应该能说明这个想法):

class-MyClass
{
公众:
void doSomeWork()
{
//使用_metricsOneValue和_metricsTwoValue作为临时值,
//调用将它们用作临时变量的其他函数,等等。
}
私人:
//仅用于doSomeWork及其调用的函数。
//值覆盖每个调用。
SomeBigClass_metricsOneValue;
SomeBigClass _metricsTwoValue;
其他类别*_数据;
}

现在,假设您需要
swap()
这个类的两个实例。最简单的实现将复制所有内容,包括旧的度量,实际上,这些度量目前并不需要,因为它们将在下次调用
doSomeWork()时被覆盖无论如何。
因此,在这种情况下,您可以通过交换指向数据结构的指针来优化
交换。

实现您自己的
交换
1函数有一个好处,那就是在赋值操作符中使用复制和交换习惯用法来管理/传输动态分配的内存

如果您有以下课程:

#include <algorithm> // std::copy
#include <cstddef> // std::size_t

class MyArray{
public:
    // (default) constructor
   MyArray(std::size_t size = 0) 
       : mSize(size), mArray(mSize ? new int[mSize]() : 0)
   { }
   // copy-constructor
   MyArray(const MyArray& other) 
       : mSize(other.mSize), mArray(mSize ? new int[mSize] : 0),
   { std::copy(other.mArray, other.mArray + mSize, mArray); }
   // destructor
   ~MyArray(){ delete [] mArray; }

private:
    std::size_t mSize;
    int* mArray;
};
你可以做:

MyArray& operator=(MyArray other){
    swap(*this, other);  
    return *this;
} 
2.要安全交换类的成员,请执行以下操作: 注:本答案中的见解借鉴自



1交换函数是一个非抛出函数,它将一个类的两个对象(成员对成员)交换。我们可能会尝试使用
std::swap
而不是提供我们自己的,但这是不可能的;
std::swap
在其实现中使用复制构造函数和复制赋值操作符,我们最终会尝试根据赋值运算符本身定义赋值运算符!

我希望是一个正常的
std::swap(std::string&,std::string&)
实现在没有任何临时变量的情况下进行交换。它应该只能够交换指针,尽管我承认小字符串优化可能会在某些实现的特定工作中遇到麻烦

您可以始终使用
std::string::swap
member函数,我的意思是,否则,它有什么意义?:)

无论如何,您都需要实现它,即使它只是move构造函数的一部分,否则默认的
std::swap(A&,A&)
实现不能做很多事情


总之,是的,您应该编写自己的
swap
函数,是的,您应该使用它来调用标准swap功能。因为两者都需要,所以不需要进行性能比较。

您没有调用默认构造函数。您正在调用移动构造函数。
MyArray& operator=(const MyArray& other){
   if (this != &other){
    // get the new data ready before we replace the old
    std::size_t newSize = other.mSize;
    int* newArray = newSize ? new int[newSize]() : 0;  
    std::copy(other.mArray, other.mArray + newSize, newArray);  
    // replace the old data  
    delete [] mArray;
    mSize = newSize;
    mArray = newArray;
}

return *this;
} 
MyArray& operator=(MyArray other){
    swap(*this, other);  
    return *this;
} 
friend void swap(MyArray& first, MyArray& second){
    using std::swap; 
    // by swapping the members of two classes,
    // the two classes are effectively swapped
    swap(first.mSize, second.mSize); 
    swap(first.mArray, second.mArray);
}
void swap(A &a, A &b)
{
   a.a.swap(b.a);
   a.b.swap(b.b);
   a.c.swap(b.c);
   a.d.swap(b.d);
}