您的位置:首页 > 编程语言 > C语言/C++

C++ Primer 学习笔记——拷贝控制

2016-03-07 14:54 399 查看
拷贝构造函数

直接初始化:编译器使用普通的函数匹配,来选择与我们提供的参数最匹配的构造函数

拷贝初始化:将右侧的对象拷贝到正在创建的对象中,通常使用拷贝构造函数来完成

调用拷贝构造函数 除了=还有,

将一个对象作为实参传递给一个非引用类型的形参

从一个返回类型为非引用的函数返回一个对象

用花括号列表初始化一个数组中的元素或一个聚合类中的成员

拷贝构造函数的参数必须是引用

返回值被用来初始化调用方的结果

拷贝赋值运算符

operator=

析构函数

~Foo();

无论何时一个对象被销毁,就会自动调用其析构函数

//HasPtr
#include<iostream>
#include<string>
using std::string;
class HasPtr
{
public:
HasPtr(const std::string &s = std::string()) :ps(new std::string(s)),i(0){}
//HasPtr(const HasPtr& tHasPtr)
//{
//  ps = new string;
//  *ps = *(tHasPtr.ps);
//  i = tHasPtr.i;
//}
HasPtr(const HasPtr& t) :ps(new string(*(t.ps))), i(t.i){}
HasPtr& operator=(const HasPtr& t)
{
i = t.i;
ps = new string;
*ps = *(t.ps);
}
~HasPtr(){ delete ps; }
private:
std::string *ps;
int i;
};


//numbered类。
#include<iostream>
using std::cout;
using std::endl;
class numbered
{
public:
numbered() { mysn++; }
numbered(const numbered& t)
{
cout << "enter" << endl;
mysn = ++t.mysn;
}
static int mysn;
};
int numbered::mysn = 0;
void f(numbered s)
{
cout << s.mysn ;
}

int main()
{
numbered a, b = a, c = b;
//创建b和c时候,适用拷贝构造函数(不论是默认的还是自定义的,)
f(a); f(b); f(c);

return 0;
}


=default

显示的要求编译器生成合成的版本

=delete

阻止拷贝/阻止赋值、

不能删除析构函数,否则无法销毁此类型的对象

//13.18
#include<iostream>
#include<string>
using namespace std;
class Employee
{
private:
string name;
int card;
static int data;
public:
Employee(string tname) :name(tname){
data++;
card = data;
}
void print()
{
cout << name << " " << card << endl;
}
};
int Employee::data = 1;
int main()
{
Employee c1("sdfa"), c2("fasf");
c1.print();
c2.print();
return 0;
}


行为像值的类

即从底层拷贝值,拷贝指针指向的值(而不是拷贝指针)

class HasPtr
{
public:
HasPtr(string &s = string()) :ps(new string(s)){}
HasPtr(const HasPtr &s)
{
ps = new string(*(s.ps));//拷贝底层string(及指针指向的值)
i = s.i;
}
HasPtr operator=(const HasPtr &s);
~HasPtr(){ delete ps; }

private:
string *ps;
int i;
};
//赋值运算符必须处理自赋值
HasPtr HasPtr::operator=(const HasPtr &s)
{
auto newp = new string(*(s.ps));
delete ps;//释放旧内存
ps = newp;
i = s.i;
return *this;
}


行为像指针的类

拷贝指针成员本身而不是他的指向

class HasPtr
{
public:
HasPtr(const string  &s = string()) :ps(new string(s)), i(0), use(new size_t(0)){}
HasPtr(const HasPtr &s) :ps(s.ps), i(s.i), use(s.use){
++*use;
}
HasPtr& operator=(const HasPtr&);
~HasPtr()
{
--*use;
if (use == 0)
{
delete ps;
delete use;
}
};
private:
string *ps;
int i;
size_t *use;
};
//赋值运算符必须处理自赋值
HasPtr& HasPtr::operator=(const HasPtr& s)
{
++*s.use;
if (--*use == 0)
{
delete ps;
delete use;
}
ps = s.ps;
i = s.i;
use = s.use;
return *this;

}


交换操作

//13.3
#include<iostream>
#include<string>
using std::string;
using std::cout;
class HasPtr
{
public:
HasPtr(string &s = string()) :ps(new string(s)){}
HasPtr(const HasPtr &s)
{
ps = new string(*(s.ps));//拷贝底层string(及指针指向的值)
i = s.i;
}
HasPtr operator=(const HasPtr &s);
~HasPtr(){ delete ps; }

//HasPtr版本的swap,如果一个类有自己特地的swap函数,调用std::swap(标准库中)就是错误的
friend void swap(HasPtr &, HasPtr &);
//在赋值运算符中使用swap,将左侧对象与右侧对象的一个副本进行交换
HasPtr& operator=( HasPtr);

private:
string *ps;
int i;
};
//赋值运算符必须处理自赋值
HasPtr HasPtr::operator=(const HasPtr &s)
{
auto newp = new string(*(s.ps));
delete ps;//释放旧内存
ps = newp;
i = s.i;
return *this;
}

inline
void swap(HasPtr &h1, HasPtr &h2)
{
cout << *(h1.ps) << " " << *(h2.ps);

using std::swap;
swap(h1.ps, h2.ps);//交换指针
swap(h1.i, h2.i);
cout << *(h1.ps) << " " << *(h2.ps);
}

HasPtr& HasPtr::operator=( HasPtr h)
{
swap(*this, h);
return *this;

}

int main()
{
string s = "123", s2 = "abc";
HasPtr h1(s), h2(s2);
swap(h1, h2);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: