IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ Primer 中文第 5 版练习答案 第 13 章 拷贝控制(33~58) -> 正文阅读

[C++知识库]C++ Primer 中文第 5 版练习答案 第 13 章 拷贝控制(33~58)

C++ Primer 中文版(第 5 版)练习解答合集

自己写的解答,如有错误之处,烦请在评论区指正!


33

如果不使用引用类型的话,Folder 类的对象可能很大,实参到形参的拷贝会影响性能。不用 const 是因为在函数内部需要对 Folder 对象进行修改

34

#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <set>
using std::set;

class Message;

class Folder {
public:
	void addMsg(Message* m);
	void remMsg(Message* m);

	void display() const;
	void showFirstMessageAddress() const {
		if (!messages.empty())
			cout << *messages.begin() << endl;
	}

private:
	set<Message*> messages;
};

class Message {
	friend void swap(Message& lhs, Message& rhs);

public:
	explicit Message(const string& str = "") :
		contents(str) { }
	Message(const Message& m) :
		contents(m.contents), folders(m.folders) {
		add_to_Folders(m);
	}
	Message& operator=(const Message& rhs) {
		remove_from_Folders();
		contents = rhs.contents;
		folders = rhs.folders;
		add_to_Folders(rhs);
		return *this;
	}
	~Message() {
		remove_from_Folders();
	}

	void save(Folder&);
	void remove(Folder&);
	void display() const {
		cout << contents << endl;
	}

private:
	string contents;
	set<Folder*> folders;

	void add_to_Folders(const Message&);
	void remove_from_Folders();
};

inline void Folder::addMsg(Message* m) {
	messages.insert(m);
}

inline void Folder::remMsg(Message* m) {
	messages.erase(m);
}

inline void Folder::display() const {
	for (const auto m : messages)
		m->display();
}

inline void Message::save(Folder& f) {
	folders.insert(&f);
	f.addMsg(this);
}

inline void Message::remove(Folder& f) {
	folders.erase(&f);
	f.remMsg(this);
}

inline void Message::add_to_Folders(const Message& m) {
	for (auto f : m.folders)
		f->addMsg(this);
}

inline void Message::remove_from_Folders() {
	for (auto f : folders)
		f->remMsg(this);
}

void swap(Message& lhs, Message& rhs) {
	using std::swap;
	for (auto f : lhs.folders)
		f->remMsg(&lhs);
	for (auto f : rhs.folders)
		f->remMsg(&rhs);
	swap(lhs.folders, rhs.folders);
	swap(lhs.contents, rhs.contents);
	for (auto f : lhs.folders)
		f->addMsg(&lhs);
	for (auto f : rhs.folders)
		f->addMsg(&rhs);
}

35

Folder 类的对象中不会正确更新包含的 Message 信息。

36

见 34 题代码

37

	void addFld(Folder* f) {
		folders.insert(f);
	}
	void remFld(Folder* f) {
		folders.erase(f);
	}

38

拷贝和交换的方式是一种通用的赋值运算符写法,能保证语义正确,并且自赋值不会出问题,但是相比现在的写法效率较低。

39

#include <iostream>
using std::cout;
using std::endl;
#include <memory>
using std::allocator;
#include <string>
using std::string;
#include <utility>
using std::pair;

class StrVec {
public:
	StrVec() :
		elements(nullptr), first_free(nullptr), cap(nullptr) {}
	StrVec(const StrVec& s) {
		auto newdata = alloc_n_copy(s.begin(), s.end());
		elements = newdata.first;
		first_free = cap = newdata.second;
	}
	StrVec& operator=(const StrVec& rhs) {
		auto data = alloc_n_copy(rhs.begin(), rhs.end());
		free();
		elements = data.first;
		first_free = cap = data.second;
		return *this;
	}
	~StrVec() {
		free();
	}
	void reserve(const size_t newcapacity) {
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}
	void resize(const size_t newSize) {
		if (newSize <= size()) {
			first_free = elements + newSize;
		} else {
			reserve(newSize);
			while (first_free != elements + newSize) {
				alloc.construct(first_free++, "");
			}
		}
	}
	void push_back(const string& s) {
		chk_n_alloc();
		alloc.construct(first_free++, s);
	}
	size_t size() const {
		return  first_free - elements;
	}
	size_t capacity() const {
		return cap - elements;
	}
	string* begin() const {
		return elements;
	}
	string* end() const {
		return first_free;
	}
	void display() const {
		for (auto it = begin(); it != end(); ++it)
			cout << *it << endl;
	}

private:
	static allocator<string> alloc;
	void chk_n_alloc() {
		if (size() == capacity())
			reallocate();
	}
	pair<string*, string*> alloc_n_copy(const string* b, const string* e) {
		auto data = alloc.allocate(e - b);
		return { data, uninitialized_copy(b, e, data) };
	}
	void free() {
		if (elements) {
			for (auto p = first_free; p != elements; /*null*/)
				alloc.destroy(--p);
			alloc.deallocate(elements, cap - elements);
		}
	}
	void reallocate() {
		auto newcapacity = size() ? 2 * size() : 1;
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}

	string* elements;
	string* first_free;
	string* cap;
};

allocator<string> StrVec::alloc;

40

	StrVec(const initializer_list<string>& list) {
		auto newdata = alloc_n_copy(list.begin(), list.end());
		elements = newdata.first;
		first_free = cap = newdata.second;
	}

41

因为 first_free 是一个尾后指针,直接在原地构造即可。使用后置递增运算的话会跳过一个位置没有构造。

42

StrVec.h:

#pragma once
#include <iostream>
using std::cout;
using std::endl;
#include <memory>
using std::allocator;
#include <string>
using std::string;
#include <utility>
using std::pair;
#include <initializer_list>
using std::initializer_list;

class StrVec {
public:
	StrVec() :
		elements(nullptr), first_free(nullptr), cap(nullptr) {}
	StrVec(const initializer_list<string>& list) {
		auto newdata = alloc_n_copy(list.begin(), list.end());
		elements = newdata.first;
		first_free = cap = newdata.second;
	}
	StrVec(const StrVec& s) {
		auto newdata = alloc_n_copy(s.begin(), s.end());
		elements = newdata.first;
		first_free = cap = newdata.second;
	}
	StrVec& operator=(const StrVec& rhs) {
		auto data = alloc_n_copy(rhs.begin(), rhs.end());
		free();
		elements = data.first;
		first_free = cap = data.second;
		return *this;
	}
	~StrVec() {
		free();
	}
	void reserve(const size_t newcapacity) {
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}
	void resize(const size_t newSize) {
		if (newSize <= size()) {
			first_free = elements + newSize;
		} else {
			reserve(newSize);
			while (first_free != elements + newSize) {
				alloc.construct(first_free++, "");
			}
		}
	}
	void push_back(const string& s) {
		chk_n_alloc();
		alloc.construct(first_free++, s);
	}
	size_t size() const {
		return  first_free - elements;
	}
	size_t capacity() const {
		return cap - elements;
	}
	string* begin() const {
		return elements;
	}
	string* end() const {
		return first_free;
	}
	string& operator[] (const int index) {
		return *(elements + index);
	}
	const string& operator[] (const int index) const {
		return *(elements + index);
	}
	void display() const {
		for (auto it = begin(); it != end(); ++it)
			cout << *it << endl;
	}

private:
	static allocator<string> alloc;
	void chk_n_alloc() {
		if (size() == capacity())
			reallocate();
	}
	pair<string*, string*> alloc_n_copy(const string* b, const string* e) {
		auto data = alloc.allocate(e - b);
		return { data, uninitialized_copy(b, e, data) };
	}
	void free() {
		if (elements) {
			for (auto p = first_free; p != elements; /*null*/)
				alloc.destroy(--p);
			alloc.deallocate(elements, cap - elements);
		}
	}
	void reallocate() {
		auto newcapacity = size() ? 2 * size() : 1;
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}

	string* elements;
	string* first_free;
	string* cap;
};

allocator<string> StrVec::alloc;

CppPrimerCh13.cpp:

#include <iostream>
#include <fstream>
#include <sstream>
#include <cassert>
#include <memory>
#include <string>
#include <set>
#include <unordered_map>
#include "StrVec.h"
using namespace std;

class QueryResult {
	string target;
	shared_ptr<StrVec> spLines;
	shared_ptr<set<int>> lineNumbers;

	friend ostream& operator<< (ostream& os, const QueryResult& qr);

public:
	QueryResult(string i_target, shared_ptr<StrVec> i_spLines, shared_ptr<set<int>> i_lineNumbers)
		: target(i_target), spLines(i_spLines), lineNumbers(i_lineNumbers) {}
};

class TextQuery {
	shared_ptr<StrVec> spLines;
	shared_ptr<unordered_map<string, set<int>>> spWordToLine;

public:
	explicit TextQuery(ifstream& infile) {
		spLines = make_shared<StrVec>();
		spWordToLine = make_shared<unordered_map<string, set<int>>>();
		string buffer, wordBuffer;
		int lineCnt = 0;
		while (getline(infile, buffer)) {
			spLines->push_back(buffer);
			istringstream iss(buffer);
			while (iss >> wordBuffer) {
				(*spWordToLine)[wordBuffer].insert(lineCnt);
			}
			++lineCnt;
		}
	}

	QueryResult query(const string& target) {
		shared_ptr<set<int>> spLineNumbers = make_shared<set<int>>((*spWordToLine)[target]);
		return QueryResult(target, spLines, spLineNumbers);
	}
};

ostream& operator<< (ostream& os, const QueryResult& qr) {
	if (qr.lineNumbers->empty()) {
		cout << qr.target << " occurs 0 times" << endl;
		return os;
	}
	cout << qr.target << " occurs " << qr.lineNumbers->size() << " times" << endl;
	for (const auto& lineNum : *(qr.lineNumbers)) {
		cout << "(line " << lineNum + 1 << ")  ";
		cout << (*qr.spLines)[lineNum] << endl;
	}
	return os;
}

void runQueries(ifstream& infile) {
	TextQuery tq(infile);
	while (true) {
		cout << "enter word to look for, or q to quit: ";
		string s;
		if (!(cin >> s) || s == "q")
			break;
		cout << tq.query(s) << endl;
	}
}

int main() {
	string filename("D:\\repos\\CppPrimerCh12\\CppPrimerCh12\\test.txt");
	ifstream infile(filename);
	assert(infile.is_open());
	runQueries(infile);
	return 0;
}

运行结果:

enter word to look for, or q to quit: I
I occurs 9 times
(line 1)  Last week I went to the theatre.
(line 2)  I had a very good seat. The play
(line 3)  was very interesting. I did not
(line 6)  They were talking loudly. I got
(line 7)  very angry. I could not hear the
(line 8)  actors. I turned round. I looked
(line 11)  In the end, I could not bear it.
(line 12)  I turned round again. 'I can't
(line 13)  hear a word!' I said angrily. '

enter word to look for, or q to quit: the
the occurs 5 times
(line 1)  Last week I went to the theatre.
(line 7)  very angry. I could not hear the
(line 9)  at the man and the woman angrily.
(line 11)  In the end, I could not bear it.
(line 14)  It's none of your business,' the

enter word to look for, or q to quit: week
week occurs 1 times
(line 1)  Last week I went to the theatre.

enter word to look for, or q to quit: ^Z

43

void free() {
    //if (elements) {
    //	for (auto p = first_free; p != elements; /*null*/)
    //		alloc.destroy(--p);
    //	alloc.deallocate(elements, cap - elements);
    //}
    for_each(elements, first_free, [this](string& s) {
        alloc.destroy(&s);
    });
    alloc.deallocate(elements, cap - elements);
}

44

#pragma once

#include <iostream>
using std::ostream;
using std::cout;
using std::endl;
#include <memory>
using std::allocator;
using std::uninitialized_copy;
#include <utility>
using std::pair;
#include <algorithm>
#include <initializer_list>
using std::initializer_list;
#include <cstring>

class String {
	friend ostream& operator<<(ostream& os, const String& s);

public:
	String() :
		elements(nullptr), first_free(nullptr), cap(nullptr) {}
	String(const char* str) {
		if (!str || !*str)
			return;
		const char* p = str;
		first_free = elements = alloc.allocate(strlen(str));
		while (*p) {
			alloc.construct(first_free++, *p);
			++p;
		}
		cap = first_free;
	}
	String(const String& str) {
		auto newdata = alloc_n_copy(str.elements, str.first_free);
		elements = newdata.first;
		first_free = cap = newdata.second;
	}
	String& operator=(const String& rhs) {
		auto data = alloc_n_copy(rhs.elements, rhs.first_free);
		free();
		elements = data.first;
		first_free = cap = data.second;
		return *this;
	}
	~String() {
		free();
	}

	void reserve(const size_t newcapacity) {
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}
	void resize(const size_t newSize) {
		if (newSize <= size()) {
			first_free = elements + newSize;
		} else {
			reserve(newSize);
			while (first_free != elements + newSize) {
				alloc.construct(first_free++, '\0');
			}
		}
	}
	void push_back(const char ch) {
		chk_n_alloc();
		alloc.construct(first_free++, ch);
	}

	size_t size() const {
		return first_free - elements;
	}
	size_t capacity() const {
		return cap - elements;
	}
	char* begin() const {
		return elements;
	}
	char* end() const {
		return first_free;
	}


private:
	static allocator<char> alloc;
	void chk_n_alloc() {
		if (size() == capacity())
			reallocate();
	}
	pair<char*, char*> alloc_n_copy(const char* b, const char* e) {
		auto data = alloc.allocate(e - b);
		return { data, uninitialized_copy(b, e, data) };
	}
	void free() {
		std::for_each(elements, first_free, [this](char& c) {
			alloc.destroy(&c);
		});
		alloc.deallocate(elements, cap - elements);
	}
	void reallocate() {
		auto newcapacity = size() ? 2 * size() : 1;
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}

	char* elements;
	char* first_free;
	char* cap;
};

allocator<char> String::alloc;

ostream& operator<<(ostream& os, const String& s) {
	for (char* p = s.begin(); p != s.end(); ++p)
		printf("%c", *p);
	return os;
}

45

右值引用是必须绑定到右值的引用,并且只能绑定到一个将要销毁的对象。右值引用通过 && 获得。

返回非引用类型的函数,连同算术,关系,位以及后置递增递减运算符,都生成右值。不能将左值引用绑定到这类表达式上。

相比而言,左值持久,右值短暂,因为右值引用只能绑定到临时对象,所以所引用的对象将要被销毁并且该对象没有其他用户。

46

int f() {
	return 2;
}

int main() {
	vector<int> vi(100);
	int&& r1 = f();			// 返回非引用类型的函数,右值引用
	int& r2 = vi[0];		// 变量,左值引用
	int& r3 = r1;			// 变量,左值引用
	int&& r4 = vi[0] * f();	// 算术运算,右值引用
	return 0;
}

47

String(const String& str) {
    cout << "Copy construct" << endl;
    auto newdata = alloc_n_copy(str.elements, str.first_free);
    elements = newdata.first;
    first_free = cap = newdata.second;
}
String& operator=(const String& rhs) {
    cout << "Copy assignment" << endl;
    auto data = alloc_n_copy(rhs.elements, rhs.first_free);
    free();
    elements = data.first;
    first_free = cap = data.second;
    return *this;
}

48

从空的 vector 开始调用 10 次 push_back,String 类被拷贝 35 次

#include "String.h"
using namespace std;

int main() {
	vector<String> vec;
	puts("**************************");
	for (int i = 0; i < 10; ++i)
		vec.push_back("Hello");
	puts("**************************");
	return 0;
}

49

StrVec:

StrVec(StrVec&& s) noexcept :
elements(s.elements), first_free(s.first_free), cap(s.cap) {
    s.elements = s.first_free = s.cap = nullptr;
}
StrVec& operator=(StrVec&& rhs) noexcept {
    if (this != &rhs) {
        free();
        elements = rhs.elements;
        first_free = rhs.first_free;
        cap = rhs.cap;
        rhs.elements = rhs.first_free = rhs.cap = nullptr;
    }
    return *this;
}

String:

String(String&& str) noexcept :
elements(str.elements), first_free(str.first_free), cap(str.cap) {
    str.elements = str.first_free = str.cap = nullptr;
}
String& operator=(String&& rhs) {
    if (this != &rhs) {
        free();
        elements = rhs.elements;
        first_free = rhs.first_free;
        cap = rhs.cap;
        rhs.elements = rhs.first_free = rhs.cap = nullptr;
    }
    return *this;
}

Message:

Message(Message&& m) :
contents(std::move(m.contents)) {
    move_Folders(&m);
}
Message& operator=(Message&& rhs) {
    if (this != &rhs) {
        remove_from_Folders();
        contents = std::move(rhs.contents);
        move_Folders(&rhs);
    }
    return *this;
}

50

和 48 题的代码一样,这次调用了 35 次移动构造函数

#include "String.h"
using namespace std;

int main() {
	vector<String> vec;
	puts("**************************");
	for (int i = 0; i < 10; ++i)
		vec.push_back("Hello");
	puts("**************************");
	return 0;
}

51

因为如果一个类既有移动构造函数,也有拷贝构造函数,编译器将使用普通的函数匹配规则来确定使用哪个构造函数。以值的方式返回一个 unique_ptr,返回的是右值,所以这里调用的是移动构造函数,不会出现问题。

52

这里确实有点绕,一开始没看看懂,把代码写了一遍才弄懂,先把相关代码贴在下面:

HasPtr.h:

#pragma once

#include<string>

class HasPtr {
    friend void swap(HasPtr& a, HasPtr& b);

public:
    HasPtr(const std::string& s = std::string()) :
        ps(new std::string(s)), i(0) {}
    HasPtr(const HasPtr& orig) :
        ps(new std::string(*(orig.ps))), i(orig.i) {
        cout << "copy constructor" << endl;
    }
    HasPtr(HasPtr&& p) noexcept : ps(p.ps), i(p.i) {
        cout << "move constructor" << endl;
        p.ps = nullptr;
    }
    HasPtr& operator=(HasPtr rhs) {
        cout << "assignment" << endl;
        swap(*this, rhs);
        return *this;
    }
    ~HasPtr() {
        delete ps;
    }
private:
    std::string* ps;
    int i;
};

inline
void swap(HasPtr& a, HasPtr& b) {
    using std::swap;
    swap(a.ps, b.ps);
    swap(a.i, b.i);
}

CppPrimerCh13.cpp:

#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include "HasPtr.h"

int main() {
	HasPtr hp(string("hello")), hp2(string("hi"));
	cout << "**********************" << endl;
	hp = hp2;
	cout << "**********************" << endl;
	hp = std::move(hp2);
	cout << "**********************" << endl;
	return 0;
}

运行结果:

**********************
copy constructor
assignment
**********************
move constructor
assignment
**********************

解释:

对于 hp = hp2;,hp2 是一个变量,所以是一个左值,直接匹配赋值运算符,在参数传递的过程中调用了一次拷贝构造运算符。在赋值运算符中,又调用了我们自定义的 swap 函数,交换了 *this 和 rhs 的成员变量,赋值运算符结束后,局部变量 rhs 被析构。

对于 hp = std::move(hp2);,std::move 将一个右值引用绑定到 hp2 上,std::move 可以调用拷贝构造函数或者移动构造函数,这里匹配了移动构造函数。我们自定义的移动构造函数返回一个 HasPtr 类型的值,传给了赋值运算符,后面发生的事情就和上面一样了。

可以看到下面这样的效率是更高的,但是用下面这样的移动赋值,hp2 就成为了移后源,其值不可用。

53

HasPtr.h:

#pragma once

#include<string>

class HasPtr {
    friend void swap(HasPtr& a, HasPtr& b);

public:
    HasPtr(const std::string& s = std::string()) :
        ps(new std::string(s)), i(0) {}
    HasPtr(const HasPtr& orig) :
        ps(new std::string(*(orig.ps))), i(orig.i) {
        cout << "copy constructor" << endl;
    }
    HasPtr(HasPtr&& p) noexcept : ps(p.ps), i(p.i) {
        cout << "move constructor" << endl;
        p.ps = nullptr;
    }
    HasPtr& operator=(const HasPtr& rhs) {
        cout << "copy assignment" << endl;
        *ps = *rhs.ps;
        i = rhs.i;
        return *this;
    }
    HasPtr& operator=(HasPtr&& rhs) noexcept {
        cout << "move assignment" << endl;
        if (this != &rhs) {
            *ps = *rhs.ps;
            i = rhs.i;
            rhs.ps = nullptr;
        }
        return *this;
    }
    ~HasPtr() {
        delete ps;
    }

private:
    std::string* ps;
    int i;
};

inline
void swap(HasPtr& a, HasPtr& b) {
    using std::swap;
    swap(a.ps, b.ps);
    swap(a.i, b.i);
}

CppPrimerCh13.cpp:

#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include "HasPtr.h"

int main() {
	HasPtr hp(string("hello")), hp2(string("hi"));
	cout << "**********************" << endl;
	hp = hp2;
	cout << "**********************" << endl;
	hp = std::move(hp2);
	cout << "**********************" << endl;
	return 0;
}

运行结果:

**********************
copy assignment
**********************
move assignment
**********************

本来在拷贝构造的时候,因为参数不是引用的,所以多了一个参数传递过程中的拷贝赋值。

本来在移动赋值的时候,先要调用一次移动构造来匹配赋值运算符,然后再过一遍赋值运算符,现在直接调用移动赋值运算符即可。

54

试了一下,发现如果写了移动构造函数的话,拷贝构造函数就是删除的。无法运行原来的程序。

55

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

56

会无限递归,最后爆栈,程序结束

#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
#include <algorithm>
using std::sort;

class Foo {
public:
	Foo sorted() &&;
	Foo sorted() const&;
private:
	vector<int> data;
};

Foo Foo::sorted() && {
	cout << "right value limited" << endl;
	sort(data.begin(), data.end());
	return *this;
}

Foo Foo::sorted() const& {
	cout << "left value limited" << endl;
	Foo ret(*this);
	return ret.sorted();
}

int main() {
	Foo f;
	f.sorted();
	return 0;
}

57

正常运行,并且正确地进行了排序,因为加一个类型转换之后,编译器认为这是一个右值,于是调用了右值引用版本的 sort

#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
#include <algorithm>
using std::sort;

class Foo {
public:
	Foo sorted() &&;
	Foo sorted() const&;
private:
	vector<int> data;
};

Foo Foo::sorted() && {
	cout << "right value limited" << endl;
	sort(data.begin(), data.end());
	return *this;
}

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

int main() {
	Foo f;
	f.sorted();
	return 0;
}

58

见 56 和 57 的代码

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:29:00  更:2021-09-22 14:31:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 21:56:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码