首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >显式要求默认移动构造器不工作吗?

显式要求默认移动构造器不工作吗?
EN

Stack Overflow用户
提问于 2021-05-14 13:55:34
回答 1查看 69关注 0票数 0

这是我的代码:

代码语言:javascript
复制
#include <cstdint>
#include <vector>

class Bar {
    uint32_t m_value;
public:
    Bar(const uint32_t value) : m_value(value) {
    }
};

class Foo {
    Bar* m_p_bar;
    uint32_t m_value;
    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;
    Foo& operator=(Foo&&) = default;
    Foo(Foo&&) = default;
public:
    /*
    Foo(Foo&& from) {
        m_p_bar = from.m_p_bar;
        m_value = from.m_value;
        from.m_p_bar = nullptr;
    }
    */
    Foo(const uint32_t value) : m_value(value) {
        m_p_bar = new Bar(value);
    }
};

int main() {
    std::vector<Foo> foos;
    foos.emplace_back(8);
}

编译器抱怨:

代码语言:javascript
复制
In file included from /opt/rh/devtoolset-9/root/usr/include/c++/9/vector:66,
                 from test_implicit_func.cpp:2:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*]’:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:307:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*; _Tp = Foo]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:329:2:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Foo*; _ForwardIterator = Foo*; _Allocator = std::allocator<Foo>]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/vector.tcc:474:3:   required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {int}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = Foo*]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/vector.tcc:121:4:   required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::reference = Foo&]’
test_implicit_func.cpp:34:21:   required from here
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
  127 |       static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
      |                                                                        ^~~~~

我注意到,出于某种原因,我需要为Foo定义自己的移动构造函数。通过显式地要求编译器使用默认的编译器(即Foo(Foo&&) = default;),它就无法工作。但是,如果我要求编译器使用所有的隐式编译器(即删除Foo(const Foo&) = delete; Foo& operator=(const Foo&) = delete; Foo& operator=(Foo&&) = default; Foo(Foo&&) = default;),那么编译器就不会抱怨。

我的问题是,为什么显式地要求编译器在这里使用默认的移动构造函数不起作用,但它在这个case中工作。这个answer建议,如果默认版本被隐式删除,我可以请求它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-14 14:12:10

如果让编译器使用隐式定义的“大5”,就会遇到泄漏和双空闲:s的问题。

您需要使移动构造函数public,并且需要在析构函数中delete指针。您还需要确保不要将指针留在moved from对象中。

代码语言:javascript
复制
#include <utility> // exchange

class Foo {
    Bar* m_p_bar;
    uint32_t m_value;

public:
    Foo(const uint32_t value) : 
        m_p_bar(new Bar(value)),
        m_value(value) 
    {}

    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;

    Foo(Foo&& rhs) :
        m_p_bar(std::exchange(rhs.m_p_bar, nullptr)),  // put a nullptr in rhs
        m_value(rhs.m_value)
    {}
    Foo& operator=(Foo&& rhs) {
        std::swap(m_p_bar, rhs.m_p_bar);     // let rhs destroy our current Bar
        m_value = rhs.m_value;
        return *this;
    }

    ~Foo() { delete m_p_bar; }               // destroy it
};

更好的方法是使用std::unique_ptr<Bar> --或者根本不使用指针。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67535566

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档