簡體   English   中英

`std :: swap`應用於這些對象時會做什么?

[英]What does `std::swap` do when applied to these objects?

編碼

using namespace std;

class A 
{
private:
  vector<int> a;
public:
  A(vector<int> x):a(x){}
  string toString()
  {
      string s;
      for (auto& element : a)
      {
          s += to_string(element) + " ";
      }
      return s;
  }
};

int main()
{
    A a1({1,2,3});
    A a2({11,12,13});

    cout << "a1 = " << a1.toString() << "\n";
    cout << "a2 = " << a2.toString() << "\n";

    swap(a1,a2);

    cout << "a1 = " << a1.toString() << "\n";
    cout << "a2 = " << a2.toString() << "\n";

    return 0;
}

預期的輸出

a1 = 1 2 3                                                                                                            
a2 = 11 12 13                                                                                                         
a1 = 11 12 13                                                                                                         
a2 = 1 2 3 

cplusplus.com> std :: swap復雜性下

非數組:常量:精確地執行一種構造和兩種分配(盡管請注意,這些操作中的每一種都基於其自身的復雜性)。

數組: N中的線性:每個元素執行交換操作。

這是否意味着將std::swap應用於a1a2僅交換指向數組[1,2,3][11,12,13]的指針,而不復制任何int或其他內容?

std::swap應用於類A兩個對象時究竟能做什么?

假設std::swap復制了數組的所有元素,我應該使用vector::swap編寫一個static A::swap函數,其時間復雜度是恆定的(來自cplusplus.com> vector :: swap ),這意味着它僅交換指針?


[..]要添加注釋,說明std::swap的語義在C ++ 17中已更改。 因此,最好提一下編譯器,其版本和目標標准。

我希望一個簡單的問題不會帶來C ++標准和編譯器版本的復雜性。 我通常在C ++ 11中編譯我的代碼。 為了完整起見,這里是筆記本電腦上的gcc版本。

$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

要求std::swap模板的type參數必須為MoveConstructible和MoveAssignable。 這表明swap可以大致寫成(省略了幾位)

void swap(T &a, T &b) {
   T tmp{std::move(a)};
   a = std::move(b);
   b = std::move(tmp);
}

對於您的示例類,它將多次調用默認的move ctor / move賦值運算符( A edit:),而它們又將調用std::vector IOW,您可以期望您的程序保持原樣的效率。

另外,您可以在與A相同的名稱空間中定義一個非成員swap函數,並使用矢量參數顯式調用std::swap 或直接調用std::vector::swap

根據您的編譯器和所使用的類/類型,使用swap函數將復制其中一個類,或使用move構造函數/賦值(C ++ 11及更高版本)( http://en.cppreference.com/w / cpp / utility / move )。

您的類僅包含一個向量,對於向量類,此move構造函數可以執行您簡單地稱為“交換指針”的操作,因此非常快。 請注意,實現例如復制構造函數將刪除隱式聲明的move構造函數,從而使這種“魔術”發生! http://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor

在獨立查看交換功能時,我給您帶來大量的后續見解:交換功能最著名的用途之一是在復制和交換習慣中( https://progdoo.wordpress.com / 2012/06/03 / c11-copy-and-swap-idiom / )。 這對於已實現的移動構造器/分配最有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM