con*_*roy 54 c++ gcc operators
我们来看一个简单的例子:
struct some_struct {
std::string str;
int a, b, c;
}
some_struct abc, abc_copy;
abc.str = "some text";
abc.a = 1;
abc.b = 2;
abc.c = 3;
abc_copy = abc;
Run Code Online (Sandbox Code Playgroud)
然后abc_copy是一个精确复制的abc..怎么可能没有定义=操作符?
(在处理一些代码时,这让我感到意外..)
Mar*_*ork 85
如果你没有定义这四种方法(C++ 11中有六种),编译器会为你生成它们:
如果你想知道为什么?
它是为了保持与C的向后兼容性(因为C结构可以使用=和声明来复制).但它也使得编写简单的类更容易.有人会争辩说,由于"浅拷贝问题",它会增加问题.我反对的论点是你不应该有一个拥有RAW指针的类.通过使用适当的智能指针,问题就会消失.
默认构造函数(如果未定义其他构造函数)
编译器生成的默认构造函数将调用基类的默认构造函数,然后每个成员默认构造函数(按它们声明的顺序)
析构函数(如果没有定义析构函数)
以声明的相反顺序调用每个成员的析构函数.然后调用基类的析构函数.
复制构造函数(如果未定义复制构造函数)
调用传递src对象的基类复制构造函数.然后使用src对象成员调用每个成员的复制构造函数作为要复制的值.
分配操作员
调用传递src对象的基类赋值运算符.然后使用src对象作为要复制的值调用每个成员上的赋值运算符.
移动构造函数(如果没有定义移动构造函数)
调用传递src对象的基类移动构造函数.然后使用src对象成员调用每个成员的move构造函数作为要移动的值.
移动分配操作员
调用传递src对象的基类移动赋值运算符.然后使用src对象作为要复制的值,在每个成员上调用move赋值运算符.
如果你定义一个这样的类:
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
};
Run Code Online (Sandbox Code Playgroud)
编译器将构建的是:
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
// Conceptually two different versions of the default constructor are built
// One is for value-initialization the other for zero-initialization
// The one used depends on how the object is declared.
// some_struct* a = new some_struct; // value-initialized
// some_struct* b = new some_struct(); // zero-initialized
// some_struct c; // value-initialized
// some_struct d = some_struct(); // zero-initialized
// Note: Just because there are conceptually two constructors does not mean
// there are actually two built.
// value-initialize version
some_struct()
: some_base() // value-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it
// PODS not initialized
, str2()
{}
// zero-initialize version
some_struct()
: some_base() // zero-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it.
, a(0)
, b(0)
, c(0) // 0 is NULL
, str2()
// Initialize all padding to zero
{}
some_struct(some_struct const& copy)
: some_base(copy)
, str1(copy.str1)
, a(copy.a)
, b(copy.b)
, c(copy.c)
, str2(copy.str2)
{}
some_struct& operator=(some_struct const& copy)
{
some_base::operator=(copy);
str1 = copy.str1;
a = copy.a;
b = copy.b;
c = copy.c;
str2 = copy.str2;
return *this;
}
~some_struct()
{}
// Note the below is pseudo code
// Also note member destruction happens after user code.
// In the compiler generated version the user code is empty
: ~str2()
// PODs don't have destructor
, ~str1()
, ~some_base();
// End of destructor here.
// In C++11 we also have Move constructor and move assignment.
some_struct(some_struct&& copy)
// ^^^^ Notice the double &&
: some_base(std::move(copy))
, str1(std::move(copy.str1))
, a(std::move(copy.a))
, b(std::move(copy.b))
, c(std::move(copy.c))
, str2(std::move(copy.str2))
{}
some_struct& operator=(some_struct&& copy)
// ^^^^ Notice the double &&
{
some_base::operator=(std::move(copy));
str1 = std::move(copy.str1);
a = std::move(copy.a);
b = std::move(copy.b);
c = std::move(copy.c);
str2 = std::move(copy.str2);
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
在C++中,结构体等同于成员默认为公共而非私有访问的类.
如果没有提供,C++编译器也会自动生成类的以下特殊成员:
为了保持与C的源兼容性,这种行为是必要的.
C不能让您定义/覆盖运算符,因此通常使用=运算符复制结构.