【问题标题】:move Constructor is not called移动构造函数未被调用
【发布时间】:2019-05-27 11:37:33
【问题描述】:

我正在实现一个用于学习 C++ 的 IntArray 类。我必须承认我还没有完全理解 r 和 lvalues 以及 move 构造函数。我想试试看我的代码是否正常工作,但我不知道为什么 {IntArray array = IntArray(5);} 没有调用我实现的移动构造函数。我认为这是一个案例。

#include "IntArray.h"
IntArray::IntArray()
    :data(nullptr), count(0), capacity(0) {std::cout << "Default Constructor called" << std::endl;}

IntArray::IntArray(int size)
    :data(new int[size]), count(size), capacity(size)  {std::cout << "Constructor called with size: " << size << std::endl;}

IntArray::~IntArray() {
    std::cout << "Destructor called" << std::endl;
    delete[] data; //rest is stack allocated and gets freed with end of scope
}

//COPY CONSTRUCT & ASSIGN OP
IntArray::IntArray(const IntArray& rhs) 
    :data(new int[rhs.count]), count(rhs.count), capacity(rhs.count) //warum nicht mit capacity? wir wollen doch eine exakte kopie?
{
    std::cout << "Copy Constructor called" << std::endl;
    std::copy(rhs.data, rhs.data + rhs.count, data); //pointer arithmetik?
}
IntArray& IntArray::operator=(const IntArray& rhs) {
    if (&rhs == this) //check for selfassign
        return *this;

    //if capacity of lhs is NOT big enough, reallocate new
    if (capacity < rhs.capacity) { 
        delete[] data;
        data = new int[rhs.count];
        capacity = rhs.count;
    }   
    count = rhs.count;
    std::copy(rhs.data, rhs.data + rhs.count, data);
    return *this;
}

//MOVE CONSTRUCT & ASSIGN OP
IntArray::IntArray(IntArray&& rhs)
    :data(rhs.data), count(rhs.count), capacity(rhs.capacity)
{
    std::cout << "Move Constructor called" << std::endl;

    rhs.data = nullptr;
    rhs.count = 0;
    rhs.capacity = 0;
}
IntArray& IntArray::operator=(IntArray&& rhs) {
    if (&rhs == this) //self assignment?
        return *this;
    std::cout << "Move assignment operator called" << std::endl;

    //steal
    delete[] data;
    data = rhs.data;
    count = rhs.count;
    capacity = rhs.capacity;

    //Reset old obj to prevent double freeing
    rhs.data = nullptr;
    rhs.count = 0;
    rhs.capacity = 0;

    return *this;
}

【问题讨论】:

  • 离题,但你的赋值运算符有一个缺陷。在调用new[] 之前释放内存。如果new[] 抛出异常,则您的对象已损坏。不要在复制构造函数中复制代码,而是通过创建一个临时的并将其换出来调用它——{IntArray t(rhs); std::swap(t.data, data); std::swap(t.capacity, capacity), std::swap(t.count,count); return *this;}——换句话说,使用copy-swap idiom

标签: c++ move-semantics move-constructor


【解决方案1】:

您看不到移动构造或移动分配只是优化的结果!请看一下“复制省略”https://en.cppreference.com/w/cpp/language/copy_elision

如果你使用 gcc,你可以告诉编译器不要优化它:

g++ -O0 main.cpp -fno-elide-constructors

现在结果是:

Constructor called with size: 5
Move Constructor called
Destructor called
Destructor called

【讨论】:

  • 寻找这种明显的行为,我遇到了这个问题和another。您能否详细说明一下以回答我从评论中复制的问题(因为我完全有同样的疑问)?问题是:[...] 每当创建临时对象的唯一目的是被复制并随后被销毁(复制省略)时,就会发生这种情况。 但这听起来与移动构造函数的预期用例完全一样?.
  • @EnricoMariaDeAngelis:你能问一个新问题吗?你的话题离这个很远。谢谢
猜你喜欢
  • 2017-09-19
  • 2015-06-27
  • 2016-07-12
  • 2018-06-01
  • 2011-05-22
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
相关资源
最近更新 更多