书籍:C++ Primer Plus (第六版)(中文版)
工具:Dev-C++ 5.11
电脑信息:Intel® Xeon® CPU E5-2603 v3 @ 1.60GHz
系统类型:64位操作系统,基于X64的处理器 windows10 专业版
第18章 探讨C++新标准
18.1 复习前面介绍过的C++11功能
实例18.1
rvref.cpp
cpp
#include <iostream>
inline double f(double tf) { return 5.0 * (tf - 32) / 9.0; };
int main()
{
// std::cout << "Hello World!\n";
using namespace std;
double tc = 21.5;
double && rd1 = 7.07;
double&& rd2 = 1.8 * tc + 32;
double&& rd3 = f(rd2);
cout << "tc value and address :" << tc <<", "<< & tc << endl;
cout << "rd1 value and address :" << rd1 << ", " << &rd1 << endl;
cout << "rd2 value and address :" << rd2 << ", " << &rd2 << endl;
cout << "rd3 value and address :" << rd3 << ", " << &rd3 << endl;
cin.get();
return 0;
}
编译运行结果:
cpp
tc value and address :21.5, 0x6ffdd8
rd1 value and address :7.07, 0x6ffde0
rd2 value and address :70.7, 0x6ffde8
rd3 value and address :21.5, 0x6ffdf0
18.2 移动语义和右值引用
实例18.2
useless.cpp
cpp
// useless.cpp -- an otherwise useless class with move semantics
#include<iostream>
using namespace std;
// interface
class Useless {
private:
int n; // number of elements
char * pc; // pointer to data
static int ct; // number of objects
void ShowObject() const;
public:
Useless();
explicit Useless(int k);
Useless(int k, char ch);
Useless(const Useless & f); // regular copy constructor
Useless(Useless && f); // move constructor
~Useless();
Useless operator+(const Useless & f) const;
// need operator=() in copy and move versions
void ShowData() const;
};
// implematation
int Useless::ct = 0;
Useless::Useless() {
++ct;
n = 0;
pc = nullptr;
cout << "default constructor called; number of objects: " << ct << endl;
ShowObject();
}
Useless::Useless(int k) : n(k) {
++ct;
cout << "int constructor called; number of objects: " << ct << endl;
pc = new char[n];
ShowObject();
}
Useless::Useless(int k, char ch) : n(k) {
++ct;
cout << "int, char constructor called; number of objects: " << ct << endl;
pc = new char[n];
for(int i = 0; i < n; i++){
pc[i] = ch;
}
ShowObject();
}
Useless::Useless(const Useless & f): n(f.n) {
++ct;
cout << "copy constructor called; number of objects: " << ct << endl;
pc = new char[n];
for (int i = 0; i < n; i++){
pc[i] = f.pc[i];
}
ShowObject();
}
Useless::Useless(Useless && f) : n(f.n) {
++ct;
cout << "move constructor called; number of objects: " << ct << endl;
pc = f.pc; // steal address
f.pc = nullptr; // give old object nothing in return
f.n = 0;
ShowObject();
}
Useless::~Useless() {
cout << "destructor called; objects left: " << --ct << endl;
cout << "deleted object:\n";
ShowObject();
delete [] pc;
}
Useless Useless::operator+(const Useless &f) const {
cout << "Entering operator+()\n";
Useless temp = Useless(n+f.n);
for (int i = 0; i < n; i++) {
temp.pc[i] = pc[i];
}
for (int i = n; i < temp.n; i++){
temp.pc[i] = f.pc[i-n];
}
cout << "temp object:\n";
cout << "Leaving operator+()\n";
return temp;
}
void Useless::ShowObject() const {
cout << "Number of element: " << n;
cout << " Data address: " << (void *) pc << endl;
}
void Useless::ShowData() const {
if (n == 0 ) {
cout << "(object empty)";
}
else {
for (int i = 0; i< n; i++){
cout << pc[i];
}
}
cout << endl;
}
// application
int main() {
{
Useless one(10, 'x');
Useless two = one; // calss copy constructor
Useless three(20, 'o');
Useless four (one + three); // calls operator+(), move contructor
cout << "object one: ";
one.ShowData();
cout << "object two: ";
two.ShowData();
cout << "object three: ";
three.ShowData();
cout << "object four: ";
four.ShowData();
}
}
编译运行结果:
cpp
int, char constructor called; number of objects: 1
Number of element: 10 Data address: 0xab1900
copy constructor called; number of objects: 2
Number of element: 10 Data address: 0xab1510
int, char constructor called; number of objects: 3
Number of element: 20 Data address: 0xab1530
Entering operator+()
int constructor called; number of objects: 4
Number of element: 30 Data address: 0xab5940
temp object:
Leaving operator+()
object one: xxxxxxxxxx
object two: xxxxxxxxxx
object three: oooooooooooooooooooo
object four: xxxxxxxxxxoooooooooooooooooooo
destructor called; objects left: 3
deleted object:
Number of element: 30 Data address: 0xab5940
destructor called; objects left: 2
deleted object:
Number of element: 20 Data address: 0xab1530
destructor called; objects left: 1
deleted object:
Number of element: 10 Data address: 0xab1510
destructor called; objects left: 0
deleted object:
Number of element: 10 Data address: 0xab1900
--------------------------------
Process exited after 0.3316 seconds with return value 0
请按任意键继续. . .
实例18.3
stdmove.cpp
cpp
// stdmove.cpp -- using std::move()
#include<iostream>
#include<utility>
// interface
class Useless {
private:
int n; // number of elements
char * pc; // pointer to data
static int ct; // number of objects
void ShowObject() const;
public:
Useless();
explicit Useless(int k);
Useless(int k, char ch);
Useless(const Useless & f); // regular copy constructor
Useless(Useless && f); // move constructor
~Useless();
Useless operator+(const Useless & f) const;
Useless & operator=(const Useless & f); // copy assignment
Useless & operator=(Useless && f); // move assignment
void ShowData() const;
};
// implementation
int Useless::ct = 0;
Useless::Useless() {
++ct;
n = 0;
pc = nullptr;
}
Useless::Useless(int k) : n(k) {
++ct;
pc = new char[n];
}
Useless::Useless(int k, char ch) : n(k) {
++ct;
pc = new char[n];
for (int i = 0; i < n; i++ ){
pc[i] = ch;
}
}
Useless::Useless(const Useless & f): n(f.n) {
++ct;
pc = new char[n];
for(int i = 0; i < n; i++ ){
pc[i] = f.pc[i];
}
}
Useless::Useless(Useless && f) : n(f.n) {
++ct;
pc = f.pc; // steal address
f.pc = nullptr; // give old object nothing in return
f.n = 0;
}
Useless::~Useless() {
delete [] pc;
}
Useless & Useless::operator=(const Useless & f) { // copy assignment
std::cout << "copy assignment operator called:\n";
if (this == &f){
return *this;
}
delete[] pc;
n = f.n;
pc = new char[f.n];
for (int i = 0; i < n; i++){
pc[i] = f.pc[i];
}
return *this;
}
Useless & Useless::operator=(Useless && f) { // move assignment
std::cout << "move assignment operator called:\n";
if (this == &f) {
return *this;
}
delete [] pc;
n = f.n;
pc = f.pc;
f.n = 0;
f.pc = nullptr;
return *this;
}
Useless Useless::operator+(const Useless &f) const {
Useless temp = Useless(n + f.n);
for (int i = 0; i< n; i++){
temp.pc[i] = pc[i];
}
for (int i = n; i < temp.n; i++){
temp.pc[i] = f.pc[i-n];
}
return temp;
}
void Useless::ShowObject() const {
std::cout << "Number of elements: " << n;
std::cout << " Data address: " << (void *) pc << std::endl;
}
void Useless::ShowData() const {
if (n == 0){
std::cout << "(object empty)";
}
else{
for (int i = 0; i < n; i++){
std::cout << pc[i];
}
}
std::cout << std::endl;
}
// application
int main(){
using std::cout;{
Useless one(10, 'x');
Useless two = one + one; // calls move contructor
cout << "object one: ";
one.ShowData();
cout << "object two: ";
two.ShowData();
Useless three, four;
cout << "three = one\n";
three = one;
cout << "now object three = ";
three.ShowData();
cout << "and object one = ";
one.ShowData();
cout << "four = one + two\n";
four = one + two; // automatic move assignment
cout << "now object four = ";
four.ShowData();
cout << "four = move(one)\n";
four = std::move(one); // forced move assignment
cout << "now object four = ";
four.ShowData();
cout << "and object one = ";
one.ShowData();
}
return 0;
}
编译运行结果:
cpp
object one: xxxxxxxxxx
object two: xxxxxxxxxxxxxxxxxxxx
three = one
copy assignment operator called:
now object three = xxxxxxxxxx
and object one = xxxxxxxxxx
four = one + two
move assignment operator called:
now object four = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
four = move(one)
move assignment operator called:
now object four = xxxxxxxxxx
and object one = (object empty)
--------------------------------
Process exited after 0.3382 seconds with return value 0
请按任意键继续. . .
18.3 新的类功能
18.4 Lamnda函数
实例18.4
lambda0.cpp
cpp
// lambda0.cpp -- using lambda expressions
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <ctime>
const long Size1 = 39L;
const long Size2 = 100*Size1;
const long Size3 = 100*Size2;
bool f3(int x) {return x % 3 == 0;}
bool f13(int x) {return x % 13 == 0;}
int main()
{
using std::cout;
std::vector<int> numbers(Size1);
std::srand(std::time(0));
std::generate(numbers.begin(), numbers.end(), std::rand);
// using function pointers
cout << "Sample size = " << Size1 << '\n';
int count3 = std::count_if(numbers.begin(), numbers.end(), f3);
cout << "Count of numbers divisible by 3: " << count3 << '\n';
int count13 = std::count_if(numbers.begin(), numbers.end(), f13);
cout << "Count of numbers divisible by 13: " << count13 << "\n\n";
// increase number of numbers
numbers.resize(Size2);
std::generate(numbers.begin(), numbers.end(), std::rand);
cout << "Sample size = " << Size2 << '\n';
// using a functor
class f_mod
{
private:
int dv;
public:
f_mod(int d = 1) : dv(d) {}
bool operator()(int x) {return x % dv == 0;}
};
count3 = std::count_if(numbers.begin(), numbers.end(), f_mod(3));
cout << "Count of numbers divisible by 3: " << count3 << '\n';
count13 = std::count_if(numbers.begin(), numbers.end(), f_mod(13));
cout << "Count of numbers divisible by 13: " << count13 << "\n\n";
// increase number of numbers again
numbers.resize(Size3);
std::generate(numbers.begin(), numbers.end(), std::rand);
cout << "Sample size = " << Size3 << '\n';
// using lambdas
count3 = std::count_if(numbers.begin(), numbers.end(),
[](int x){return x % 3 == 0;});
cout << "Count of numbers divisible by 3: " << count3 << '\n';
count13 = std::count_if(numbers.begin(), numbers.end(),
[](int x){return x % 13 == 0;});
cout << "Count of numbers divisible by 13: " << count13 << '\n';
// std::cin.get();
return 0;
}
编译运行结果:
cpp
Sample size = 39
Count of numbers divisible by 3: 15
Count of numbers divisible by 13: 2
Sample size = 3900
Count of numbers divisible by 3: 1340
Count of numbers divisible by 13: 304
Sample size = 390000
Count of numbers divisible by 3: 129983
Count of numbers divisible by 13: 30221
--------------------------------
Process exited after 0.3764 seconds with return value 0
请按任意键继续. . .
实例18.5
lambda1.cpp
cpp
// lambda1.cpp -- use captured variables
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <ctime>
const long Size = 390000L;
int main()
{
using std::cout;
std::vector<int> numbers(Size);
std::srand(std::time(0));
std::generate(numbers.begin(), numbers.end(), std::rand);
cout << "Sample size = " << Size << '\n';
// using lambdas
int count3 = std::count_if(numbers.begin(), numbers.end(),
[](int x){return x % 3 == 0;});
cout << "Count of numbers divisible by 3: " << count3 << '\n';
int count13 = 0;
std::for_each(numbers.begin(), numbers.end(),
[&count13](int x){count13 += x % 13 == 0;});
cout << "Count of numbers divisible by 13: " << count13 << '\n';
// using a single lambda
count3 = count13 = 0;
std::for_each(numbers.begin(), numbers.end(),
[&](int x){count3 += x % 3 == 0; count13 += x % 13 == 0;});
cout << "Count of numbers divisible by 3: " << count3 << '\n';
cout << "Count of numbers divisible by 13: " << count13 << '\n';
// std::cin.get();
return 0;
}
编译运行结果:
cpp
Sample size = 390000
Count of numbers divisible by 3: 129681
Count of numbers divisible by 13: 30080
Count of numbers divisible by 3: 129681
Count of numbers divisible by 13: 30080
--------------------------------
Process exited after 0.9402 seconds with return value 0
请按任意键继续. . .
18.5 包装器
实例18.6
somedefs.h
cpp
// somedefs.h
#include <iostream>
template <typename T, typename F>
T use_f(T v, F f)
{
static int count = 0;
count++;
std::cout << "use_f count = " << count
<< ", &count = " << &count << std::endl;
return f(v);
}
class Fp
{
private:
double z_;
public:
Fp(double z = 1.0) : z_(z) {}
double operator()(double p) { return z_*p; }
};
class Fq
{
private:
double z_;
public:
Fq(double z = 1.0) : z_(z) {}
double operator()(double q) { return z_+ q; }
};
callable.cpp
cpp
// callable.cpp -- callable types and templates
#include <iostream>
#include"somedefs.h"
using namespace std;
double dub(double x) { return 2.0 * x; }
double square(double x) { return x * x; }
int main()
{
double y = 1.21;
cout << "Function pointer dub:\n";
cout << " " << use_f(y, dub) << endl;
cout << "Function pointer sqrt:\n";
cout << " " << use_f(y, square) << endl;
cout << "Function object Fp:\n";
cout << " " << use_f(y, Fp(5.0)) << endl;
cout << "Function object Fq:\n";
cout << " " << use_f(y, Fq(5.0)) << endl;
cout << "Lambda expression 1:\n";
cout << " " << use_f(y, [](double u) {return u * u; }) << endl;
cout << "Lambda expresson 2:\n";
cout << " " << use_f(y, [](double u) {return u + u / 2.0; }) << endl;
return 0;
}
编译运行结果:
cpp
Function pointer dub:
use_f count = 1, &count = 0x487060
2.42
Function pointer sqrt:
use_f count = 2, &count = 0x487060
1.4641
Function object Fp:
use_f count = 1, &count = 0x487040
6.05
Function object Fq:
use_f count = 1, &count = 0x487050
6.21
Lambda expression 1:
use_f count = 1, &count = 0x4a7034
1.4641
Lambda expresson 2:
use_f count = 1, &count = 0x4a7038
1.815
--------------------------------
Process exited after 0.3259 seconds with return value 0
请按任意键继续. . .
实例18.8
wrapped.cpp
cpp
// wrapped0.cpp -- using a function wrapper
#include "somedefs.h"
#include <iostream>
#include <math.h>
#include <functional>
double dub(double x) { return 2.0 * x; }
double sqaure(double x) { return x * x; }
int main()
{
using std::cout;
using std::endl;
using std::function;
double y = 1.21;
function<double(double)> ef1 = dub;
function<double(double)> ef2 = sqaure;
function<double(double)> ef3 = Fq(10.0);
function<double(double)> ef4 = Fp(10.0);
function<double(double)> ef5 = [](double u) {return u * u; };
function<double(double)> ef6 = [](double u) {return u + u / 2.0; };
cout<<"Function pointer dub:\n";
cout << use_f(y, ef1) << endl;
cout<<"Function pointer square:\n";
cout << use_f(y, ef2) << endl;
cout<<"Function object Fp:\n";
cout << use_f(y, ef3) << endl;
cout<<"Function object FQ:\n";
cout << use_f(y, ef4) << endl;
cout<<"Function expression 1:\n";
cout << use_f(y, ef5) << endl;
cout<<"Function expression 2:\n";
cout << use_f(y, ef6) << endl;
return 0;
}
编译运行结果:
cpp
Function pointer dub:
use_f count = 1, &count = 0x489040
2.42
Function pointer square:
use_f count = 2, &count = 0x489040
1.4641
Function object Fp:
use_f count = 3, &count = 0x489040
11.21
Function object FQ:
use_f count = 4, &count = 0x489040
12.1
Function expression 1:
use_f count = 5, &count = 0x489040
1.4641
Function expression 2:
use_f count = 6, &count = 0x489040
1.815
--------------------------------
Process exited after 0.2212 seconds with return value 0
请按任意键继续. . .
18.6 可变参数模板
实例18.9
variadic1.cpp
cpp
//variadic1.cpp -- using recursion to unpack a parameter pack
#include <iostream>
#include <string>
// definition for 0 parameters -- terminating call
void show_list3() {}
// definition for 1 or more parameters
template<typename T, typename... Args>
void show_list3(T value, Args... args)
{
std::cout << value << ", ";
show_list3(args...);
}
int main()
{
int n = 14;
double x = 2.71828;
std::string mr = "Mr. String objects!";
show_list3(n, x);
show_list3(x*x, '!', 7, mr);
return 0;
}
编译运行结果:
cpp
14, 2.71828, 7.38905, !, 7, Mr. String objects!,
--------------------------------
Process exited after 0.323 seconds with return value 0
请按任意键继续. . .
实例18.10
variadic2.cpp
cpp
// variadic2.cpp
#include <iostream>
#include <string>
// definition for 0 parameters
void show_list() {}
// definition for 1 parameter
template<typename T>
void show_list(const T& value)
{
std::cout << value << '\n';
}
// definition for 2 or more parameters
template<typename T, typename... Args>
void show_list(const T& value, const Args&... args)
{
std::cout << value << ", ";
show_list(args...);
}
int main()
{
int n = 14;
double x = 2.71828;
std::string mr = "Mr. String objects!";
show_list(n, x);
show_list(x*x, '!', 7, mr);
return 0;
}
编译运行结果:
cpp
14, 2.71828
7.38905, !, 7, Mr. String objects!
--------------------------------
Process exited after 0.3245 seconds with return value 0
请按任意键继续. . .
18.7 C++11新增的其他功能
18.8 语言变化
实例18.11
lexcast.cpp
cpp
// lexcast.cpp -- simple cast from float to string
#include <iostream>
#include <string>
#include "boost/lexical_cast.hpp"
int main()
{
using namespace std;
cout << "Enter your weight: ";
float weight;
cin >> weight;
string gain = "A 10% increase raises ";
string wt = boost::lexical_cast<string>(weight);
gain = gain + wt + " to "; // string operator+()
weight = 1.1 * weight;
gain = gain + boost::lexical_cast<string>(weight) + ".";
cout << gain << endl;
return 0;
}
编译运行结果:
没有安装boost库,编译失败!
18.9 接下来的任务
附录E 其它运算符
E.1 按位运算符
E.2 成员解除引用运算符
实例E.1 memb_pt.cpp
cpp
// memb_pt.cpp -- simple cast from float to string
#include <iostream>
using namespace std;
class Example
{
private:
int feet;
int inches;
public:
Example();
Example(int ft);
~Example();
void show_in() const;
void show_ft() const;
void use_ptr() const;
};
Example::Example()
{
feet=0;
inches=0;
}
Example::Example(int ft)
{
feet=ft;
inches=12*feet;
}
Example::~Example()
{
}
void Example::show_in() const
{
cout<<inches<<" inches\n";
}
void Example::show_ft() const
{
cout<<feet<<" feet\n";
}
void Example::use_ptr() const
{
Example yard(3);
int Example::*pt;
pt=&Example::inches;
cout<<" Set pt to &Example::inches:\n";
cout<<" this->pt:"<<this->*pt<<endl;
cout<<" yard.*pt:"<<yard.*pt<<endl;
pt=&Example::feet;
cout<<" Set pt to &Example::feet:\n";
cout<<" this->pt:"<<this->*pt<<endl;
cout<<" yard.*pt:"<<yard.*pt<<endl;
void(Example::*pf)() const;
pf=&Example::show_in;
cout<<" Set pf to &Example::show_in:\n";
cout<<" Using (this->*pf)(): ";
(this->*pf)();
cout<<" Using (yard.*pt)(): ";
(yard.*pf)();
}
int main()
{
Example car(15);
Example van(20);
Example garage;
cout << "car use_ptr() output:\n";
car.use_ptr();
cout<<"\nvan.use_ptr() output:\n";
van.use_ptr();
return 0;
}
编译运行结果:
cpp
car use_ptr() output:
Set pt to &Example::inches:
this->pt:180
yard.*pt:36
Set pt to &Example::feet:
this->pt:15
yard.*pt:3
Set pf to &Example::show_in:
Using (this->*pf)(): 180 inches
Using (yard.*pt)(): 36 inches
van.use_ptr() output:
Set pt to &Example::inches:
this->pt:240
yard.*pt:36
Set pt to &Example::feet:
this->pt:20
yard.*pt:3
Set pf to &Example::show_in:
Using (this->*pf)(): 240 inches
Using (yard.*pt)(): 36 inches
--------------------------------
Process exited after 0.319 seconds with return value 0
请按任意键继续. . .
附录E.3 alignof (C++11)
实例E.2 align.cpp
cpp
// memb_pt.cpp -- simple cast from float to string
#include <iostream>
using namespace std;
class things1
{
char ch;
int a;
double x;
};
class things2
{
int a;
double x;
char ch;
};
int main()
{
things1 th1;
things2 th2;
cout << "char alignment: "<<alignof(char)<<endl;
cout << "int alignment: "<<alignof(int)<<endl;
cout << "double alignment: "<<alignof(double)<<endl;
cout << "thing1 alignment: "<<alignof(things1)<<endl;
cout << "thing2 alignment: "<<alignof(things2)<<endl;
cout << "thing1 size: "<<sizeof(things1)<<endl;
cout << "thing2 size: "<<sizeof(things2)<<endl;
return 0;
}
编译运行结果:
cpp
char alignment: 1
int alignment: 4
double alignment: 8
thing1 alignment: 8
thing2 alignment: 8
thing1 size: 16
thing2 size: 24
--------------------------------
Process exited after 0.3231 seconds with return value 0
请按任意键继续. . .