Table of Contents
C++ Classes
explicit
对于只有一个参数的构造函数,应该将其声明为explicit,以避免隐式转换带来的难以查找的BUG。
mutable
C++中mutable关键字存在的必要性是什么? – invalid s的回答 – 知乎 https://www.zhihu.com/question/64969053/answer/226142449
声明为mutable的成员变量,可以在const成员函数中被修改。
声明变量时尽量使用花括号初始化
像下面的代码,可能本意是想声明一个变量,但实际上却是声明了一个函数:
IntCell obj4();
而用花括号初始化,则没有歧义:
IntCell obj4{};
使用initializer list初始化vector
vector<int> daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
或者不需要使用等号:
vector<int> daysInMonth{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
C++ Details
动态创建对象
m = new IntCell();
m = new IntCell{}; // C++11
m = new IntCell;
上述3种创建对象的方法都可以用。
左值,右值和引用
左值:标识了一个非临时对象的表达式。
右值:标识了一个临时对象或者不和任何对象关联的表达式。
函数的返回值可能是左值(如*ptr
,arr[x]
,cin>>x>>y
),也可能是右值。
传递参数
call-by-value
call-by-constant-reference
call-by-lvalue-reference
call-by-rvalue-reference
返回值(Return Passing)
return-by-value
return-by-reference
std::swap与std::move
通过右值引用来实现swap:
void swap(vector<string> &x, vector<string> &y)
{
vector<string> tmp = static_cast<vector<string>&&>(x);
x = static_cast<vector<string>&&>(y);
y = static_cast<vector<string>&&>(tmp);
}
或者使用move
函数也是一样的效果:
void swap(vector<string> &x, vector<string> &y)
{
vector<string> tmp = std::move(x);
x = std::move(y);
y = std::move(tmp);
}
The Big Five
C++为每个类提供的5个带有默认实现的函数:destructor,copy constructor,move constructor,copy assignment operator,move assignment operator。
destructor
默认实现对每个类成员调用析构函数。
Copy Constructor and Move Constructor
用于在声明一个对象的时候,将这个对象初始化为另一个对象所处的状态。如果另一个对象是左值,那么调用的是Copy Constructor,如果另一个对象是右值,那么调用的是Move Constructor。
有3种应用场景,
1.声明的时候;
IntCell B = C;
IntCell B{C};
上面两种声明方式等价。
2.作为函数的参数并且使用值传递的时候(不能是通过引用传递参数);
3.作为函数的返回值并且是return by value(不能是返回引用);
copy constructord的默认实现对类成员依次调用各自的copy constructor。
move contructor的默认实现对类成员依次调用copy constructor或者move constructor(如果相应的类成员具有move constructor)。
Copy Assignment and Move Assignment (operator=)
对于lhs=rhs
这种表达式,如果rhs是左值,那么就调用copy assignment operator,如果rhs是右值,那么就调用move assignment operator。
copy assignment operator的默认实现对类的每一个成员调用其相应的copy assignment operator。
move assignment operator的默认实现对类成员调用copy assignment operator或者move assignment operator(如果相应的类成员具有move assignment operator)。
对于big five的5个函数,要么就都用默认的,要么就重写其中的某些函数并将其余的标记为default或者delete。
copy assignment operator常按照copy and swap idiom实现。
big five5个函数的signature:
destructor
~ class-name ();
virtual ~ class-name ();
decl-specifier-seq(optional) ~ class-name () = default; // since c++11
decl-specifier-seq(optional) ~ class-name () = delete; // since c++11
attr(optional) decl-specifier-seq(optional) id-expression ( void(optional) ) except(optional) attr(optional) requires-clause(optional); // since c++20
copy constructor
class-name ( const class-name & );
class-name ( const class-name & ) = default; // since c++11
class-name ( const class-name & ) = delete; // since c++11
move constructor
class-name ( class-name && );
class-name ( class-name && ) = default;
class-name ( class-name && ) = delete;
copy assignment operator
class-name & class-name :: operator= ( class-name );
class-name & class-name :: operator= ( const class-name & );
class-name & class-name :: operator= ( const class-name & ) = default; // since c++11
class-name & class-name :: operator= ( const class-name & ) = delete; // since c++11
move assignment operator
class-name & class-name :: operator= ( class-name && );
class-name & class-name :: operator= ( class-name && ) = default;
class-name & class-name :: operator= ( class-name && ) = delete;
实现move assignment operator或者move constructor会导致copy assignment operator和copy constructor的默认实现被删除;
同样实现copy assignment operator和copy constructor也会导致move assignment operator和move constructor的默认实现被删除。
近期评论