2

コード

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下の複雑さ

非配列:定数: 1 つの構成と 2 つの代入を正確に実行します (ただし、これらの操作はそれぞれ独自の複雑さで機能することに注意してください)。

Array: Linear in N: 要素ごとにスワップ操作を実行します。

std::swapに適用されa1a2ポインターを配列にスワップするだけで、[1,2,3][11,12,13]のものはコピーしないということintですか?

std::swapclass の 2 つのオブジェクトに適用すると、正確にはどうなりAますか?

std::swap配列のすべての要素をコピーすると仮定すると、時間の複雑さが一定であるstatic A::swap関数を作成する必要があります ( cplusplus.com > vector::swapから)。つまり、ポインターのみをスワップしますか?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
4

2 に答える 2

1

使用しているコンパイラとクラス/型に応じて、swap 関数はクラスの 1 つをコピーするか、移動コンストラクタ/代入を使用します (C++11 以降) ( http://en.cppreference.com/w /cpp/utility/move )。

クラスはベクトルのみで構成され、ベクトル クラスの場合、このムーブ コンストラクターは単に「ポインターの交換」と呼ばれることを行うため、非常に高速です。たとえば、コピー コンストラクターを実装すると、暗黙的に宣言された移動コンストラクターが削除され、この「魔法」が発生することに注意してください!! ( http://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor )

スワップ関数を個別に見ていく中で、なだれのフォローアップの洞察を提供します: スワップ関数の最も有名な用途の 1 つは、コピー アンド スワップ イディオム ( https://progdoo.wordpress.com /2012/06/03/c11-copy-and-swap-idiom/ )。これは、実装された移動コンストラクター/割り当てで最も効率的に機能します。

于 2018-02-19T08:06:23.577 に答える