Valid tive C ++, 3rd edition, item 25: consider supporting a non-throwing swap (on)

Source: Internet
Author: User

Item 25: consider supporting a non-throwing swap (without throwing an exception swap)

By Scott Meyers

Translator: fatalerror99 (itepub's nirvana)

Release: http://blog.csdn.net/fatalerror99/

Swap is an interesting function. It was first introduced as a component of STL, and later became the pillar of exception-safe programming (abnormal security programming) (see item 29) and General mechanism to suppress the possibility of self-assignment (see item 11 ). Because swap is so useful, it is very important to implement it as appropriate, but with its extraordinary importance it comes a series of extraordinary complexity. In this item, we will study exactly what these complexities are and how to deal with them.

Swap(Exchange) two objects values send their own values to each other. By default, switching through standard swap algorithms is a very mature technology. The typical implementation fully meets your expectation:

Namespace STD {

Template <typename T> // typical Implementation of STD: swap;
Void swap (T & A, T & B) // swaps A's and B's values
{
T temp ();
A = B;
B = temp;
}
}

As long as your type supports copying (via copy constructor (copy constructor) and copy assignment operator (copy assignment operator), the default swap implementation can switch your type objects, you do not need to do any special support work.

However, the default swap implementation may be less cool. It involves copying three objects: From A to temp, from B to A, and from temp to B. For some types, these replicas are unnecessary. For this type, the default swap is like letting you take the express train into the alley.

The most important of such types is those mainly composed of one pointer, which points to another type that contains real data. A common manifestation of this design method is "pimpl idiom" ("pointer to implementation" -- See item 31 ). A widget class using this design may look like this:

Class widgetimpl {// class for widget data;
Public: // details are unimportant
...

PRIVATE:
Int A, B, C; // possibly lots of data-
STD: vector <double> V; // expensive to copy!
...
};

Class widget {// class using the pimpl Idiom
Public:
Widget (const widget & RHs );

Widget & operator = (const widget & RHs) // to copy a widget, copy its
{// Widgetimpl object.
... // Details on implementing
* Pimpl = * (RHS. pimpl); // operator = in general,
... // See items 10, 11, and 12.
}
...

PRIVATE:
Widgetimpl * pimpl; // PTR to object with this
}; // Widget's data

To exchange the objects values of these two widgets, all we need to do is to exchange their pimpl pointers (pointer), but the default swap algorithm cannot know this. It not only needs to copy three widgets, but also has three widgetimpl objects, which is too inefficient. It's not cool at all.

What we want to do is to tell STD: swap that when we exchange widgets, the way to execute the exchange is swap's internal pimpl pointers. The formal saying of this method is: specialize STD: swap for widget (specially crafted for the widget STD: swap ). The following is a basic idea, although it cannot be compiled in this form:

Namespace STD {

Template <>// This is a specialized version
Void swap<Widget>(Widget & A, // of STD: swap for when T is
Widget & B) // widget;This won't compile
{
Swap (A. pimpl, B. pimpl); // to swap widgets, just swap
} // Their pimpl pointers
}

The "template <>" at the beginning of this function indicates that this isTotal template Specialization(Full template specialization) (some books are called "Full template specialization" or "complete template specialization" -- Translator's note). The "<widget>" after the function name indicates this specialization (special) it occurs when T is a widget. In other words, this implementation should be used when a general SWAP template (Template) is used for widgets. Generally, we are not allowed to change the content in STD namespace, but we are allowed to completely customize standard templates (such as SWAP) for the type (such as widgets) We create ourselves ). This is what we are doing here.

However, as I said, this function cannot be compiled. That's because it tries to access pimpl pointers (pointers) inside a and B, while they are private. We can declare our specialization (special) as a friend, but the Convention is different: it allows the widget to declare a public member function (Public member function) named swap) perform the actual exchange, and then convert STD: swap to call the member function (member function ):

Class widget {// same as abve, cannot for
Public: // addition of the SWAp mem func
...
Void swap (widget & other)
{
Using STD: swap; // The need for this Declaration
// Is explained later in this item

Swap (pimpl, other. pimpl); // to swap widgets, swap their
} // Pimpl pointers

...
};

Namespace STD {

Template <> // revised specialization
Void swap <widget> (widget & A, // STD: swap
Widget & B)
{
A. Swap (B); // To swap widgets, call their
} // Swap member function
}

This is not only compiled, but also consistent with STL containers (container). All STL containers (containers) provide both public swap member functions (Public swap member function ), it also provides the specializations (special) of STD: swap that calls these member functions (member functions ).

However, assume that the widget and widgetimpl are ClassTemplates(Class template), instead of classes (class), we may be able to parameterize the data types stored in widgetimpl:

Template <typename T>
Class widgetimpl {...};

Template <typename T>
Class widget {...};

Adding a swap member function (member function) to the widget (add one in widgetimpl if needed) is as easy as before, but we specialize in STD :: swap problems. This is the code we want to write:

Namespace STD {
Template <typename T>
Void swap <widget <t>(Widget <t> & A, // error! Illegal code!
Widget <t> & B)
{A. Swap (B );}
}

This seems reasonable, but it is illegal. We try to partially specialize (partially Special) a function template (function template) (STD: swap), but although C ++ allows class templates (class template) but function templates (function template) is not allowed to do so. Such Code cannot be compiled (although some compilers mistakenly accept it ).

When we want to "partially specialize" ("partially special") a function templates (function template), we usually simply add an overload (overload ). It looks like this:

Namespace STD {

Template <typename T> // An overloading of STD: swap
VoidSwap(Widget <t> & A, // (note the lack of "<...>" after
Widget <t> & B) // "Swap"), but see below
{A. Swap (B);} // why this isn't valid Code
}

In general, the overload function templates (function template) is really good, but STD is a special namespace, and the rules for managing it are also special. It recognizes the templates (Template) in STD, but it does not recognize the additionNewTemplates (new template) (or classes, or functions, or anything else ). The content of STD is determined by the C ++ Standardization Committee separately, and we are prohibited from adding the decisions we make to them. In addition, the prohibited methods make you helpless. Programs that break this ban can indeed compile and run, but their behavior is undefined. If you want your software to behave as expected, you should not add new things to STD.

(This Article is not complete. Click here to answer the next article)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.