了解和使用副本分配构造函数

Ste*_*ail 4 c++ copy-assignment

我试图了解副本分配构造函数在c ++中的工作方式。我只使用过Java,所以我真的不在这里。我已经阅读并看到返回引用是一种很好的做法,但是我不知道该怎么做。我写了这个小程序来测试这个概念:

main.cpp:

#include <iostream>
#include "test.h"

using namespace std;

int main() {
    Test t1,t2;
    t1.setAge(10);
    t1.setId('a');
    t2.setAge(20);
    t2.setId('b');

    cout << "T2 (before) : " << t2.getAge() << t2.getID() << "\n";

    t2 = t1; // calls assignment operator, same as t2.operator=(t1)

    cout << "T2 (assignment operator called) : " << t2.getAge() << t2.getID() << "\n";

    Test t3 = t1; // copy constr, same as Test t3(t1)

    cout << "T3 (copy constructor using T1) : " << t3.getAge() << t3.getID() << "\n";

    return 1;
}
Run Code Online (Sandbox Code Playgroud)

test.h:

class Test {
    int age;
    char id;

    public:
        Test(){};
        Test(const Test& t); // copy
        Test& operator=(const Test& obj); // copy assign
        ~Test();
        void setAge(int a);
        void setId(char i);
        int getAge() const {return age;};
        char getID() const {return id;};
};
Run Code Online (Sandbox Code Playgroud)

test.cpp:

#include "test.h"

void Test::setAge(int a) {
    age = a;
}

void Test::setId(char i) {
    id = i;
}

Test::Test(const Test& t) {
    age = t.getAge();
    id = t.getID();
}

Test& Test::operator=(const Test& t) {

}

Test::~Test() {};
Run Code Online (Sandbox Code Playgroud)

我似乎不明白我应该放什么东西operator=()。我见过有人回来了*this,但从我读到的内容仅是对象本身的引用(在的左侧=),对吗?然后,我想到了返回const Test& t对象的副本,但是使用该构造函数没有意义了吗?我要返回什么,为什么?

R S*_*ahu 5

我已经阅读并看到返回引用是一种很好的做法,但是我不知道该怎么做。

怎么样

return *this;
Run Code Online (Sandbox Code Playgroud)

as the last line in the function.

Test& Test::operator=(const Test& t) {
   ...
   return *this;
}
Run Code Online (Sandbox Code Playgroud)

Why

As to the question of why you should return *this, the answer is that it is idiomatic.

For fundamental types, you can use things like:

int i;
i = 10;
i = someFunction();
Run Code Online (Sandbox Code Playgroud)

You can use them in a chain operation.

int j = i = someFunction();
Run Code Online (Sandbox Code Playgroud)

You can use them in a conditional.

if ( (i = someFunction()) != 0 ) { /* Do something */ }
Run Code Online (Sandbox Code Playgroud)

You can use them in a function call.

foo((i = someFunction());
Run Code Online (Sandbox Code Playgroud)

They work because i = ... evaluates to a reference to i. It's idiomatic to keep that semantic even for user defined types. You should be able to use:

Test a;
Test b;

b = a = someFunctionThatReturnsTest();

if ( (a = omeFunctionThatReturnsTest()).getAge() > 20 ) { /* Do something */ }
Run Code Online (Sandbox Code Playgroud)

But Then

More importantly, you should avoid writing a destructor, a copy constructor, and a copy assignment operator for the posted class. The compiler created implementations will be sufficient for Test.

  • “ *我见过人们返回`* this`,但是从我读到的内容仅仅是对象本身的引用(在=的左边),对吗?*”听起来OP知道他们应该这样做做。也许您可以为“为什么”添加一些解释,这是正确的(因为这似乎是他们所缺少的)。 (3认同)
  • @ scohe001我不知道建议编写副本构造函数然后在副本构造函数内调用赋值运算符是否是一个好主意。最好让复制构造函数自行运行,然后使用copy / swap根据复制构造函数简单地实现赋值运算符。 (3认同)
  • @SteliosPapamichail,我可以建议/sf/ask/292090571/和/sf/ask/229568041/交换成语 (3认同)
  • @Stelios-如果需要分配资源,则赋值运算符还有一个释放当前资源的附加步骤,而副本构造函数则不这样做。将所有代码从复制构造函数移动到赋值运算符之类的方法都混淆了这一区别。您需要确保副本构造函数具有“空”资源,否则赋值运算符将尝试取消分配垃圾。这就是海事组织的危险。我见过很多次程序员忘记将指向资源的指针清空为空,然后调用赋值运算符,只是发生了段错误。 (3认同)
  • 一定要阅读三法则的链接。如果没有良好的三则规则,就不能编写健壮的,平凡的C ++代码。基于副本构造函数而不是其他方法编写赋值运算符可以消除一些代码(无法实现自赋值),通过破坏副本来自动释放资源,并且移动赋值是免费的。 (2认同)