C++ 为什么 = 运算符在没有定义的情况下对结构起作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1575181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does the = operator work on structs without having been defined?
提问by conejoroy
Let's look at a simple example:
让我们看一个简单的例子:
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;
Then abc_copy is an exact copyof abc
.. how is it possible withoutdefining the = operator?
那么 abc_copy 是..的精确副本,abc
怎么可能不定义= 运算符?
(This took me by surprise when working on some code..)
(这让我在处理一些代码时感到惊讶..)
回答by Martin York
If you do not define these four methods (six in C++11) the compiler will generate them for you:
如果您没有定义这四个方法(C++11 中有六个),编译器将为您生成它们:
- Default Constructor
- Copy Constructor
- Assignment Operator
- Destructor
- Move Constructor (C++11)
- Move Assignment (C++11)
- 默认构造函数
- 复制构造函数
- 赋值运算符
- 析构函数
- 移动构造函数 (C++11)
- 移动赋值 (C++11)
If you want to know why?
It is to maintain backward compatibility with C (because C structs are copyable using = and in declaration). But it also makes writing simple classes easier. Some would argue that it adds problems because of the "shallow copy problem". My argument against that is that you should not have a class with owned RAW pointers in it. By using the appropriate smart pointers that problem goes away.
如果你想知道为什么?
它是为了保持与 C 的向后兼容性(因为 C 结构可以使用 = 和 in 声明进行复制)。但它也使编写简单的类变得更容易。有些人会争辩说,由于“浅拷贝问题”,它增加了问题。我反对的论点是你不应该有一个拥有自己的 RAW 指针的类。通过使用适当的智能指针,问题就消失了。
Default Constructor (If no other constructors are defined)
默认构造函数(如果没有定义其他构造函数)
The compiler generated default constructor will call the base classes default constructor and then each members default constructor (in the order they are declared)
编译器生成的默认构造函数将调用基类的默认构造函数,然后调用每个成员的默认构造函数(按它们声明的顺序)
Destructor (If no destructor defined)
析构函数(如果没有定义析构函数)
Calls the destructor of each member in reverse order of declaration. Then calls the destructor of the base class.
以与声明相反的顺序调用每个成员的析构函数。然后调用基类的析构函数。
Copy Constructor (If no copy constructor is defined)
复制构造函数(如果没有定义复制构造函数)
Calls the base class copy constructor passing the src object. Then calls the copy constructor of each member using the src objects members as the value to be copied.
调用传递 src 对象的基类复制构造函数。然后使用 src 对象成员作为要复制的值调用每个成员的复制构造函数。
Assignment Operator
赋值运算符
Calls the base class assignment operator passing the src object. Then calls the assignment operator on each member using the src object as the value to be copied.
调用传递 src 对象的基类赋值运算符。然后使用 src 对象作为要复制的值对每个成员调用赋值运算符。
Move Constructor (If no move constructor is defined)
移动构造函数(如果没有定义移动构造函数)
Calls the base class move constructor passing the src object. Then calls the move constructor of each member using the src objects members as the value to be moved.
调用传递 src 对象的基类移动构造函数。然后使用 src 对象成员作为要移动的值调用每个成员的移动构造函数。
Move Assignment Operator
移动赋值运算符
Calls the base class move assignment operator passing the src object. Then calls the move assignment operator on each member using the src object as the value to be copied.
调用传递 src 对象的基类移动赋值运算符。然后使用 src 对象作为要复制的值对每个成员调用移动赋值运算符。
If you define a class like this:
如果你定义一个这样的类:
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
};
What the compiler will build is:
编译器将构建的是:
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;
}
};
回答by MHarris
In C++, structs are equivalent to classes where members default to public rather than private access.
在 C++ 中,结构等价于成员默认为公共访问而不是私有访问的类。
C++ compilers will also generate the following special members of a class automatically if they are not provided:
如果未提供,C++ 编译器还将自动生成类的以下特殊成员:
- Default constructor- no arguments, default initalizes everything.
- Copy constructor- ie a method with the same name as the class, that takes a reference to another object of the same class. Copies all values across.
- Destructor- Called when the object is destroyed. By default does nothing.
- Assignment operator- Called when one struct/class is assigned to another. This is the automatically generated method that's being called in the above case.
- 默认构造函数- 无参数,默认初始化所有内容。
- 复制构造函数——即与类同名的方法,它引用同一个类的另一个对象。复制所有值。
- Destructor- 当对象被销毁时调用。默认情况下什么都不做。
- 赋值运算符- 当一个结构/类分配给另一个时调用。这是在上述情况下调用的自动生成的方法。
回答by Ferruccio
That behavior is necessary in order to maintain source compatibility with C.
为了保持与 C 的源代码兼容性,这种行为是必要的。
C does not give you the ability to define/override operators, so structs are normally copied with the = operator.
C 不提供定义/覆盖运算符的能力,因此通常使用 = 运算符复制结构。
回答by eran
But it is defined. In the standard. If you supply no operator =, one is supplied to you. And the default operator just copies each of the member variables. And how does it know which way to copy each member? it calls their operator = (which, if not defined, is supplied by default...).
但它是定义的。在标准中。如果您不提供运算符 =,则会向您提供一个。而默认操作符只是复制每个成员变量。它如何知道复制每个成员的方式?它调用它们的运算符 =(如果未定义,则默认提供...)。
回答by Sam Harwell
The assignment operator(operator=
) is one of the implicitly generated functions for a struct or class in C++.
的赋值运算符(operator=
)是用于在C ++结构或类隐式生成的功能之一。
Here is a reference describing the 4 implicitly generated members:
http://www.cs.ucf.edu/~leavens/larchc++manual/lcpp_136.html
这是描述 4 个隐式生成成员的参考:http:
//www.cs.ucf.edu/~leavens/larchc++manual/lcpp_136.html
In short, the implicitly generated member performs a memberwise shallow copy. Here is the long version from the linked page:
简而言之,隐式生成的成员执行成员浅拷贝。这是链接页面的长版本:
The implicitly-generated assignment operator specification, when needed, is the following. The specification says that the result is the object being assigned (
self
), and that the value of the abstract value ofself
in the post-stateself
" is the same as the value of the abstract value of the argumentfrom
.
需要时,隐式生成的赋值运算符规范如下。规范说结果是被赋值的对象(
self
),并且self
后状态self
中的抽象值的值与参数的抽象值的值相同from
。
// @(#)$Id: default_assignment_op.lh,v 1.3 1998/08/27 22:42:13 leavens Exp $
#include "default_interfaces.lh"
T& T::operator = (const T& from) throw();
//@ behavior {
//@ requires assigned(from, any) /\ assigned(from\any, any);
//@ modifies self;
//@ ensures result = self /\ self" = from\any\any;
//@ ensures redundantly assigned(self, post) /\ assigned(self', post);
// thus
//@ ensures redundantly assigned(result, post) /\ assigned(result', post);
//@ }
回答by Troubadour
The compiler will synthesise some members for you if you don't define them explicitly yourself. The assignment operator is one of them. A copy constructor is another, and you get a destructor too. You also get a default constructor if you don't provide any constructors of your own. Beyond that I'm not sure what else but I believe there may be others (the link in the answer given by 280Z28 suggests otherwise though and I can't remember where I read it now so maybe it's only four).
如果你自己没有明确定义它们,编译器会为你合成一些成员。赋值运算符就是其中之一。复制构造函数是另一个,你也会得到一个析构函数。如果您不提供任何自己的构造函数,您也会得到一个默认构造函数。除此之外,我不确定还有什么,但我相信可能还有其他的(280Z28 给出的答案中的链接暗示并非如此,我现在不记得我在哪里读过它,所以也许只有四个)。
回答by Scott M.
structs are basically a concatenation of its components in memory (with some possible padding built in for alignment). When you assign one struct the value of another, the values are just coped over.
结构基本上是它在内存中的组件的串联(内置一些可能的填充以进行对齐)。当您为一个结构分配另一个结构的值时,这些值就被处理了。