简体   繁体   中英

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

The code

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;
}

outputs as expected

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

From cplusplus.com > std::swap under complexity

Non-array: Constant: Performs exactly one construction and two assignments (although notice that each of these operations works on its own complexity).

Array: Linear in N: performs a swap operation per element.

Does it mean that std::swap when applied to a1 and a2 only swaps the pointers to the arrays [1,2,3] and [11,12,13] but does not copy any int or anything else?

What exactly does std::swap does when applied to two objects of the class A ?

Assuming the std::swap copies all elements of the array, should I write a static A::swap function, using vector::swap whose time complexity is constant (from cplusplus.com > vector::swap ) meaning that it only swaps the pointers?


[..] want to add a note that the semantics of std::swap is changed in C++17. So it might be a good idea to mention compiler, version of it and what standard you target.

I was hoping that a simple looking question would not have brought about complexities about C++ standards and compiler versions. I typically compile my code in C++11. For the sake of completeness here is the gcc version on my laptop.

$ 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

There is a requirement that the type parameter to the std::swap template is MoveConstructible and MoveAssignable. This suggests that the swap can be written roughly as (a few bits omitted)

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

For your example class, it'll invoke the default move ctor/move assignment operators (edit: of A ) a few times and they in turn will invoke those of std::vector . IOW, you can expect your program to be reasonably efficient as is.

Alternatively, you can define a non-member swap function in the same namespace as A and call explicitly std::swap with vector parameters. Or call directly std::vector::swap .

Depending on your compiler and the classes/types you are using the swap function will either copy one of the classes, or use the move constructor/assignment (C++11 and upwards) ( http://en.cppreference.com/w/cpp/utility/move ).

Your class only consists of a vector and for vector classes this move constructor does what you refer to as simply "swapping pointers", so it will be very quick. Just be aware that implementing eg a copy constructor will delete the implicitly-declared move constructor which makes this 'magic' happen!! ( http://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor )

While looking at the swap function independently, I'm giving you an avalanche of followup-insights: One of the most famous uses of the swap-function happens in the copy-and-swap idiom ( https://progdoo.wordpress.com/2012/06/03/c11-copy-and-swap-idiom/ ). This works most efficiently with implemented move-constructors/assignments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM