【发布时间】:2015-03-24 14:47:48
【问题描述】:
我试图了解 C++ 11 移动语义的工作原理。我已经实现了一个类,它包装了一个指向 String 对象的指针,但是移动构造函数和移动赋值运算符都没有按预期调用。
我通过 Eclipse CDT 使用 GCC 4.7.2:
你能帮我理解原因吗?
#include <iostream>
#include <string>
#include <utility>
using namespace std;
class StringPointerWrapper {
public:
// Default constructor with default value
StringPointerWrapper(const std::string& s = "Empty"): ps(new std::string(s)) {
std::cout << "Default constructor: " << *ps << std::endl;
}
//Copy constructor
StringPointerWrapper(const StringPointerWrapper& other): ps(new std::string(*other.ps)) {
std::cout << "Copy constructor: " << *other.ps << std::endl;
}
//Copy assignment operator
StringPointerWrapper& operator=(StringPointerWrapper other) {
std::cout << "Assignment operator (ref): " << *other.ps << std::endl;
swap(ps, other.ps);
return *this;
}
//Alternate copy assignment operator
/*StringPointerWrapper& operator=(StringPointerWrapper& other) {
std::cout << "Assignment operator (val)" << std::endl;
//We need to do the copy by ourself
StringPointerWrapper temp(other);
swap(ps, temp.ps);
return *this;
}*/
//Move constructor
StringPointerWrapper(StringPointerWrapper&& other) noexcept : ps(nullptr) {
std::cout << "Move constructor: " << *other.ps << std::endl;
ps = other.ps;
other.ps = nullptr;
}
//Move assignment operator
StringPointerWrapper& operator= (StringPointerWrapper&& other) noexcept {
std::cout << "Move assignment operator: " << *other.ps << std::endl;
if(this != &other) {
delete ps;
ps = other.ps;
other.ps = nullptr;
}
return *this;
}
//Destructor
~StringPointerWrapper() {
std::cout << "Destroying: " << *this << std::endl;
delete ps;
}
private:
friend std::ostream& operator<<(std::ostream& os, StringPointerWrapper& spw) {
os << *spw.ps;
return os;
}
std::string *ps;
};
int main(int argc, char *argv[]) {
StringPointerWrapper spw1("This is a string");
StringPointerWrapper spw2;
StringPointerWrapper spw3("This is another string");
StringPointerWrapper spw4 = {"This is a const string"};
StringPointerWrapper spw5(StringPointerWrapper("String for move constructor"));
std::cout << "spw2 before: " << spw2 << std::endl;
spw2 = spw3;
std::cout << "spw2 after: " << spw2 << std::endl;
StringPointerWrapper spw6 = StringPointerWrapper("String for move assignment");
std::cout << spw1 << std::endl;
std::cout << spw2 << std::endl;
std::cout << spw3 << std::endl;
std::cout << spw4 << std::endl;
std::cout << spw5 << std::endl;
std::cout << spw6 << std::endl;
}
【问题讨论】:
-
首先,这可能不是理解移动语义的最佳示例。
std::string基本上是char *的包装器,因此您正在围绕指向 char 数组指针的包装器的指针构建包装器。 -
你能给出输出吗?
-
输出为: 默认构造函数:这是一个字符串 默认构造函数:空 默认构造函数:这是另一个字符串 默认构造函数:这是一个常量字符串 默认构造函数:用于移动构造函数 spw2 之前的字符串:空副本构造函数:这是另一个字符串 赋值运算符(ref):这是另一个字符串 销毁:空 spw2 after:这是另一个字符串 默认构造函数:用于移动赋值的字符串 这是一个字符串 这是另一个字符串 这是另一个字符串 这是一个 const 字符串移动构造函数的字符串 移动赋值的字符串 所有调用的析构函数
标签: c++ c++11 constructor variable-assignment move-semantics