Что делает `std :: swap` применительно к этим объектам?

Код

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 под сложность

Non-массив: Константа: выполняет ровно одну конструкцию и два присвоения (хотя обратите внимание, что каждая из этих операций работает по-своему).

Массив: Линейный по N: выполняет операцию подстановки для каждого элемента.

Означает ли это, что std::swap применительно к a1 а также a2 только меняет указатели на массивы [1,2,3] а также [11,12,13] но не копирует int или что-нибудь еще?

Что именно делает std::swap делает применительно к двум объектам класса A?

Предполагая, что std::swap копирует все элементы массива, я должен написать static A::swap функция, используя vector::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

1

Решение

Существует требование, чтобы параметр типа std::swap шаблон
MoveConstructible и MoveAssignable. Это говорит о том, что swap может быть записано примерно как (несколько бит опущены)

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

Для вашего примера класса он будет вызывать стандартные операторы перемещения ctor / move (edit: of A) несколько раз, и они в свою очередь будут вызывать те из std::vector,
Итак, вы можете ожидать, что ваша программа будет достаточно эффективной, как есть.

Кроме того, вы можете определить не-член swap функция в том же пространстве имен, что и A и позвонить явно std::swap с векторными параметрами. Или позвоните напрямую std::vector::swap,

3

Другие решения

В зависимости от вашего компилятора и классов / типов, которые вы используете, функция swap либо скопирует один из классов, либо использует конструктор / присваивание перемещения (C ++ 11 и выше) (http://en.cppreference.com/w/cpp/utility/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/). Это работает наиболее эффективно с реализованными конструкторами / заданиями перемещения.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector