【问题标题】:c++ copy assignment and move assignment are not being called没有调用 c++ 复制分配和移动分配
【发布时间】:2017-11-18 07:33:24
【问题描述】:

我正在尝试实现复制和移动分配,但我不明白应该如何使用它们。我已阅读以下主题
When did copy assignment operator called?
但它对我不起作用。

类:

class Directory{

    string name;
public:
        Directory(string name):name(name) {

        }
        ~Directory() {
            cout << "Deleting was called" <<endl;

            }

        Directory& operator=(Directory& other){
            cout << "cp assigment" <<endl;
            return *this;
        }
        Directory& operator=(Directory&& other){
            cout << "move assigment" <<endl;
            return *this;
        }
};

主要

int main()
{

    Directory* dir = new Directory("alex");
    Directory* dir2;
    dir = dir2;

    cout<<"done"<<endl;
};

我想知道何时调用复制分配和移动分配。提前致谢。

【问题讨论】:

  • 在您的情况下,分配是针对指针 (Directory*) 完成的。删除 *s 和 new 即可。
  • 您正在使用指针,您希望如何调用副本??
  • dir = dir2; 调用内置指针复制赋值运算符,而不是您的类复制赋值运算符。
  • 顺便说一句。 dir2 未初始化。因此,在dir = dir2; 之后,dir 具有相同的值并且指向newed 实例的指针丢失。这是内存泄漏。
  • 删除函数的使用:你必须定义一个拷贝构造函数。我总是不太确定复制构造函数何时不是自动定义的。但实际上最好关注rule of 5。 (因此,我不知道,因为我不需要知道。)

标签: c++ copy-assignment move-assignment-operator


【解决方案1】:

我的第一条评论,我建议删除所有*s 和new

因此主函数变为:

int main()
{
  Directory dir = Directory("alex");
  Directory dir2;
  dir2 = dir; // <-- fixed, original was: dir = dir2;

  cout<<"done"<<endl;
  return 0; // <-- fixed, return is strictly recommended for every non-void function
}

正在编译...

错误Directory dir = Directory("alex"); 有问题(使用已删除的复制构造函数)。

复制构造函数用于用Directory("alex")创建的临时实例初始化dir

这很容易改变:

int main()
{
  Directory dir("alex"); // <-- fixed: direct construction
  Directory dir2;
  dir2 = dir;

  cout<<"done"<<endl;
  return 0;
}

正在编译...

错误Directory dir2; 有问题。

是的。你定义了构造函数Directory(string name);。这会抑制此处需要的默认构造函数的自动创建。

我们可以将默认构造函数添加到class Directory

  Directory() = default;

或者我们可以改进现有的非默认构造函数,使其也可以用作默认构造函数:

  Directory(string name = string()): name(name) { }

全部来源:

#include <iostream>
#include <string>
using namespace std;

class Directory{

    string name;
public:
        Directory(string name = string()):name(name) {

        }
        ~Directory() {
            cout << "Deleting was called" <<endl;

            }

        Directory& operator=(Directory& other){
            cout << "cp assigment" <<endl;
            return *this;
        }
        Directory& operator=(Directory&& other){
            cout << "move assigment" <<endl;
            return *this;
        }
};

int main() {
    //Directory dir = Directory("alex");
    Directory dir("alex");
    Directory dir2;
    dir2 = dir;

    cout<<"done"<<endl;
    // your code goes here
    return 0;
}

现在,它可以编译并运行了。

输出:

cp assigment
done
Deleting was called
Deleting was called

你可以在ideone上看到它。

【讨论】:

    【解决方案2】:

    也许可以这样尝试:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Directory{
    public:
           string name;
    
            Directory() {
                cout << "Constructor 1 was called" <<endl;            
            }
    
            Directory(string name):name(name) {
                cout << "Constructor 2 was called" <<endl;            
            }
    
            ~Directory() {
                cout << "Deleting was called" <<endl;
            }
    
            Directory(const Directory& other){
                cout << "cp cons" <<endl;
            }
    
            Directory& operator=(const Directory& other){
                cout << "cp assigment" <<endl;
                return *this;
            }
    
            Directory& operator=(Directory&& other){
                cout << "move assigment" <<endl;
                return *this;
            }
    };
    
    
    int main()
    {
    
        Directory dir = Directory("alex");
        Directory dir2;
        dir2 = dir;
    
        cout << "done " << dir.name << dir2.name << endl;
    };
    

    我更改了代码使其不使用指针,添加了额外的构造函数(注意复制构造函数)并添加了一些额外的打印。

    我得到这个输出:

    Constructor 2 was called
    Constructor 1 was called
    cp assigment
    done alex
    Deleting was called
    Deleting was called
    

    从这里你可以看到你的复制分配不正确,因为它仍然打印“alex”,但我猜你只对被调用的函数感兴趣,而不是他们做什么。

    【讨论】:

    • 感谢您的努力。真的行。我正在尝试从这个例子中学习。我不明白为什么您的代码有效,而我的代码无效。修改后的主要部分是相同的。
    • @AlexLavriv - 你是否像我一样添加了复制构造函数?
    • @AlexLavriv - 这个链接可能会让你感兴趣:stackoverflow.com/a/9945598/4386427
    • 我现在已经添加了。它有效。但它不使用它。出于某种原因,移动分配需要提供复制构造函数。这是一种非常奇怪的行为。
    • @AlexLavriv - 不涉及移动分配。这是一个省略了临时(即Directory("alex");)的优化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 2019-07-20
    • 1970-01-01
    • 2012-07-21
    • 2020-06-21
    • 2015-03-09
    • 2019-08-09
    相关资源
    最近更新 更多