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.