The Copy-and-Swap Idiom
This post is a cross-post from www.ModernesCpp.com .
An idiom is an architectural or design pattern implementation in a concrete programming language. Applying them is idiomatic for a programming language. Today. I write about the Copy-and-Swap Idiom in C++. This idiom gives you the strong exception safety guarantee.
Before I write about the Copy-and-Swap Idiom, I should first clarify the strong exception safety guarantee. Here are a few general thoughts about error handling:
Error Handling
When you handle an error, the following aspects should be considered:
You should use exceptions for error handling. In the document "Exception-Safety in Generic Components " David Abrahams formalized what exception-safety means.
Abrahams Guarantees
Abrahams Guarantees describe a contract that is fundamental if you think about exception safety. Here are the four levels of the contract:
In general, you should at least aim for the basic exception safety guarantee. This means that you don't have resource leaks in case of an error, and your program is always in a well-defined state. If your program is not in a well-defined state after an error, there is only one option left: shut down your program.
I stated that the Copy-and-Swap Idiom provides a strong exception safety guarantee. This is a stronger guarantee, such as the basic exception safety guarantee.
Modernes C++ Mentoring
Stay Informed: Subscribe Here.
The Copy-and-Swap Idiom
Okay, I know what copy means. Therefore, let me write about swap:
The swap function
For a type to be a regular type, it has to support a swap function. A more informal definition of regular type is a value-like type that behaves like an int. I will write about regular types in an upcoming post. According to the rules "C.83: For value-like types, consider providing a noexcept swap function " and "C.85: Make swap noexcept " of the C++ Core Guidelines, a swap function should not fail and be noexcept.
The following data type Foo has a swap function.
class Foo {
public:
void swap(Foo& rhs) noexcept {
m1.swap(rhs.m1);
std::swap(m2, rhs.m2);
}
private:
Bar m1;
int m2;
};
For convenience reasons, you should consider supporting a non-member swap function based on the already implemented swap member function.
void swap(Foo& a, Foo& b) noexcept {
a.swap(b);
}
If you do not provide a non-member swap function, then the standard library algorithms that require swapping (such as std::sort and std::rotate) will fall back to the std::swap template, which is defined in terms of move construction and move assignment.
template<typename T>
void std::swap(T& a, T& b) noexcept {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
The C++ standard offers more than 40 overloads of std::swap . You can use the swap function as a building block for many idioms, such as copy construction or move assignment.
This brings me to the Copy-and-Swap Idiom.
Copy-And-Swap
If you use the Copy-and-Swap Idiom to implement the copy assignment and the move assignment operator, you must define your own swap — either as a member function or as a friend. I added a swap function to the class Cont and used it in the copy assignment and move assignment operator.
领英推荐
class Cont {
public:
// ...
Cont& operator = (const Cont& rhs);
Cont& operator = (Cont&& rhs) noexcept;
friend void swap(Cont& lhs, Cont& rhs) noexcept {
swap(lhs.size, rhs.size);
swap(lhs.pdata, rhs.pdata);
}
private:
int* pData;
std::size_t size;
};
Cont& Cont::operator = (const Cont& rhs) {
Cont tmp(rhs); // (1)
swap(*this, tmp); // (3)
return *this;
}
Cont& Cont::operator = (Cont&& rhs) {
Cont tmp(std::move(rhs)); // (2)
swap(*this, tmp); // (3)
return *this;
}
Both assignment operators make a temporary copy tmp of the source object (lines 1 and ) and then apply the swap function to it (lines 3 and 4). When the used swap functions are noexcept, the copy assignment operator and the move assignment operator support the strong exception safety guarantee. This means that both assignment operators guarantee that the operations call will be fully rolled back in case of an error such as the error never happened.
Operations supporting the Copy-and-Swap Idiom allow you to program in a transaction-based style. You prepare an operation (working on the copy) and publish the operation (swap the result) when it is fine. The Copy-and-Swap Idiom is a very powerful idiom that is applied pretty often.
When a swap function is based on copy semantics instead of move semantics, a swap function may fail because of memory exhaustion. The following implementation contradicts the C++ Core Guidelines rule "C++94: A swap function must not fail ".This is the C++98 implementation of std::swap.
template<typename T>
void std::swap(T& a, T& b) {
T tmp = a;
a = b;
b = tmp;
}
?In this case, memory exhaustion may cause a std::bad_alloc exception.
What's Next?
Partial Function Application is a technique in which a function binds a few of its arguments and returns a function taking fewer arguments. This technique is related to a technique used in functional languages called currying.
A Short Break
I will make a short two weeks Christmas Break. My next post will be published on Monday, the 9th of January. Have a good time,
Thanks a lot to my Patreon Supporters : Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dr?ge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschl?ger, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, and Phillip Diekmann.
Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, Ralf Abramowitsch, John Nebel, Mipko, and Alicja Kaminska.
My special thanks to Embarcadero
My special thanks to PVS-Studio
?
Seminars
I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
Bookable (Online)
German
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
New
Contact Me