> 文章列表 > C++ Primer第五版_第十三章习题答案(51~58)

C++ Primer第五版_第十三章习题答案(51~58)

C++ Primer第五版_第十三章习题答案(51~58)

文章目录

      • 练习13.51
      • 练习13.52
      • 练习13.53
        • 头文件
        • CPP文件
      • 练习13.54
      • 练习13.55
      • 练习13.56
      • 练习13.57
      • 练习13.48

练习13.51

虽然 unique_ptr 不能拷贝,但我们在12.1.5节中编写了一个 clone 函数,它以值的方式返回一个 unique_ptr。解释为什么函数是合法的,以及为什么它能正确工作。

在这里是移动的操作而不是拷贝操作,因此是合法的。

练习13.52

详细解释第478页中的 HasPtr 对象的赋值发生了什么?特别是,一步一步描述 hp、hp2 以及 HasPtr 的赋值运算符中的参数 rhs 的值发生了什么变化。

左值被拷贝,右值被移动。

练习13.53

从底层效率的角度看,HasPtr 的赋值运算符并不理想,解释为什么?为 HasPtr 实现一个拷贝赋值运算符和一个移动赋值运算符,并比较你的新的移动赋值运算符中执行的操作和拷贝并交换版本中的执行的操作。

头文件

#ifndef CP5_ex13_53_h
#define CP5_ex13_53_h#include <string>class HasPtr
{
public:friend void swap(HasPtr&, HasPtr&);HasPtr(const std::string &s = std::string());HasPtr(const HasPtr &hp);HasPtr(HasPtr &&p) noexcept;HasPtr& operator=(HasPtr rhs);//HasPtr& operator=(const HasPtr &rhs);//HasPtr& operator=(HasPtr &&rhs) noexcept;~HasPtr();private:std::string *ps;int i;
};#endif // CP5_ex13_53_h

CPP文件

#include "exercise13_53.h"
#include <iostream>inline void swap(HasPtr &lhs, HasPtr &rhs)
{using std::swap;swap(lhs.ps, rhs.ps);swap(lhs.i, rhs.i);std::cout << "call swap" << std::endl;
}HasPtr::HasPtr(const std::string &s) : ps(new std::string(s)), i(0)
{std::cout << "call constructor" << std::endl;
}HasPtr::HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i)
{std::cout << "call copy constructor" << std::endl;
}HasPtr::HasPtr(HasPtr &&p) noexcept : ps(p.ps), i(p.i)
{p.ps = 0;std::cout << "call move constructor" << std::endl;
}HasPtr& HasPtr::operator=(HasPtr rhs)
{swap(*this, rhs);return *this;
}HasPtr::~HasPtr()
{std::cout << "call destructor" << std::endl;delete ps;
}

练习13.54

如果我们为 HasPtr 定义了移动赋值运算符,但未改变拷贝并交换运算符,会发生什么?编写代码验证你的答案。

error: ambiguous overload for 'operator=' (operand types are 'HasPtr' and 'std::remove_reference<HasPtr&>::type { aka HasPtr }')
hp1 = std::move(*pH);
^

练习13.55

为你的 StrBlob 添加一个右值引用版本的 push_back。

void push_back(string &&s) { data->push_back(std::move(s)); }

练习13.56

如果 sorted 定义如下,会发生什么?

Foo Foo::sorted() const & {Foo ret(*this);return ret.sorted();
}

会产生递归并且最终溢出。

练习13.57

如果 sorted定义如下,会发生什么:

Foo Foo::sorted() const & { return Foo(*this).sorted(); }

没问题。会调用移动版本。

练习13.48

编写新版本的 Foo 类,其 sorted 函数中有打印语句,测试这个类,来验证你对前两题的答案是否正确。

#include <vector>
#include <iostream>
#include <algorithm>using std::vector; using std::sort;class Foo
{
public:Foo sorted() && ;Foo sorted() const &;
private:vector<int> data;
};Foo Foo::sorted() && {sort(data.begin(), data.end());std::cout << "&&" << std::endl; // debugreturn *this;
}Foo Foo::sorted() const &
{//    Foo ret(*this);//    sort(ret.data.begin(), ret.data.end());//    return ret;std::cout << "const &" << std::endl; // debug//    Foo ret(*this);//    ret.sorted();     // Exercise 13.56//    return ret;return Foo(*this).sorted(); // Exercise 13.57
}int main()
{Foo().sorted(); // call "&&"Foo f;f.sorted(); // call "const &"
}