- Mastering the C++17 STL
- Arthur O'Dwyer
- 249字
- 2021-07-08 10:20:27
Pitfalls with non-noexcept move constructors
Recall the implementation of vector::resize() from section Resizing a std::vector. When the vector resizes, it reallocates its underlying array and moves its elements into the new array--unless the element type is not "nothrow move-constructible," in which case it copies its elements! What this means is that resizing a vector of your own class type will be unnecessarily "pessimized" unless you go out of your way to specify that your move constructor is noexcept.
Consider the following class definitions:
struct Bad {
int x = 0;
Bad() = default;
Bad(const Bad&) { puts("copy Bad"); }
Bad(Bad&&) { puts("move Bad"); }
};
struct Good {
int x = 0;
Good() = default;
Good(const Good&) { puts("copy Good"); }
Good(Good&&) noexcept { puts("move Good"); }
};
class ImplicitlyGood {
std::string x;
Good y;
};
class ImplicitlyBad {
std::string x;
Bad y;
};
We can test the behavior of these classes in isolation using a test harness such as the following. Running test() will print "copy Bad--move Good--copy Bad--move Good." What an appropriate mantra!
template<class T>
void test_resizing()
{
std::vector<T> vec(1);
// Force a reallocation on the vector.
vec.resize(vec.capacity() + 1);
}
void test()
{
test_resizing<Good>();
test_resizing<Bad>();
test_resizing<ImplicitlyGood>();
test_resizing<ImplicitlyBad>();
}
This is a subtle and arcane point, but it can have a major effect on the efficiency of your C++ code in practice. A good rule of thumb is: Whenever you declare your own move constructor or swap function, make sure you declare it noexcept.
- 流量的秘密:Google Analytics網站分析與優化技巧(第2版)
- CockroachDB權威指南
- Spring Boot+Spring Cloud+Vue+Element項目實戰:手把手教你開發權限管理系統
- Java Web及其框架技術
- MariaDB High Performance
- 軟件項目管理實用教程
- ASP.NET 3.5程序設計與項目實踐
- 數據結構案例教程(C/C++版)
- Keras深度學習實戰
- C語言程序設計
- Arduino計算機視覺編程
- JSP程序設計實例教程(第2版)
- 超簡單:Photoshop+JavaScript+Python智能修圖與圖像自動化處理
- Hands-On Dependency Injection in Go
- 快樂編程:青少年思維訓練