微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – std :: unique_ptr删除函数,initializer_list – 驱动分配

所有,

当我使用初始化列表格式实例化窗口小部件数组时,指向成员变量窗口小部件实例的裸指针编译但在更改为std :: unique_ptr<>之后gcc给出了有关已删除函数的编译错误.

$uname -a

Linux .. 3.5.0-21-generic#32-Ubuntu SMP Tue Dec 11 18:51:59 UTC 2012 x86_64 x86_64 x86_64 GNU / Linux

$g –version

g(Ubuntu / Linaro 4.7.2-5ubuntu1)4.7.2

代码提供以下编译器错误

#include <stdlib.h>
#include <memory>

class Widget
{
public:
    Widget() {}
};

class W1 : public Widget
{
public:
    W1() {}
};

class W2 : public Widget
{
public:
    W2() {}
};

class WFactory
{
public:
    WFactory(const int i)   : _w(new W1()) {}
    WFactory(const char* s) : _w(new W2()) {}

    ~WFactory() { _w.reset(nullptr); }
    // ~WFactory() { delete _w; }  <--- for naked ptr

private:
    // NOTE: does not compile
    std::unique_ptr<Widget>  _w; 
    // NOTE: does compile
    // Widget* _w;
};

int main()
{
    std::unique_ptr<Widget> a(new W1()); // <--- compiles fine

    WFactory wf[] { 4,"msg" };          // <--- compiler error using unique_ptr<>
}

错误

$g++ -o unique_ptr  -std=c++11 -Wall  unique_ptr.cpp 
unique_ptr.cpp: In function ‘int main()’:
unique_ptr.cpp:36:30: error: use of deleted function ‘WFactory::WFactory(const WFactory&)’
unique_ptr.cpp:22:7: note: ‘WFactory::WFactory(const WFactory&)’ is implicitly deleted because the default deFinition would be ill-formed:
unique_ptr.cpp:22:7: error: use of deleted function ‘std::unique_ptr<_Tp,_Dp>::unique_ptr(const std::unique_ptr<_Tp,_Dp>&) [with _Tp = Widget; _Dp = std::default_delete<Widget>; std::unique_ptr<_Tp,_Dp> = std::unique_ptr<Widget>]’
In file included from /usr/include/c++/4.7/memory:86:0,from unique_ptr.cpp:2:
/usr/include/c++/4.7/bits/unique_ptr.h:262:7: error: declared here
unique_ptr.cpp:36:30: error: use of deleted function ‘WFactory::WFactory(const WFactory&)’
unique_ptr.cpp:36:14: warning: unused variable ‘wf’ [-Wunused-variable]

我对这两种情况都感到茫然:幕后产生删除fcxn的机制;或者更简单地说,为什么std :: unique_ptr<>的表现力?与裸体相比,似乎受到限制.

我的问题是:

>飞行员错误
>编译错误
>我可以将我想要的代码用于某些更改吗?

谢谢.

编辑1

根据您的回答,我很感激,我可以对WFactory进行以下更改:

(标记为不道德的代码)

class WFactory
{
public:
    WFactory(const WFactory& wf)
    {
        (const_cast<WFactory&>(wf)).moveto(_w);
    }

    WFactory(const int i)   : _w(new W1()) {}
    WFactory(const char* s) : _w(new W2()) {}

    ~WFactory() { _w.reset(nullptr); }

    void moveto(std::unique_ptr<Widget>& w)
    {
        w = std::move(_w);
    }
private:
    std::unique_ptr<Widget>  _w; 
};

现在程序编译并运行.我很欣赏标准人员出于某种原因编写了规范,因此我将我的结果作为一个善意的专业化发布在我的案例中,我真的想强调ptr的独特性.

编辑2

基于Jonathan的回复,以下代码不会抑制隐式移动ctor:

class WFactory
{
public:
    WFactory(const int i)   : _w(new W1()) {}
    WFactory(const char* s) : _w(new W2()) {}

private:
    std::unique_ptr<Widget>  _w; 
};

请注意,根本没有~WFactory(){..}.

也许有ya-ans,但我发现在Main()中使用c 11样式迭代而不是wf []会带来no-copy-ctor-for-WFactory错误.那是:

int Main()
..
    WFactory wf[] { 4,"msg" };

    for ( WFactory iwf : wf )    <---- compiler error again
        // ..

    for (unsigned i = 0; i < 2; ++i)  <--- gcc happy
        wf[i] //  ..
}

我想,新的c 11风格迭代正在进行对象复制,这是不言而喻的.

解决方法

根据C 11标准第8.5.1 / 2段:

When an aggregate is initialized by an initializer list,as specified in 8.5.4,the elements of the initializer listare taken as initializers for the members of the aggregate,in increasing subscript or member order. Each member is copy-initialized from the corresponding initializer-clause. […]

然后,对于每个元素,复制初始化涉及创建目标类型的临时值,然后使用该临时值来复制构造数组的元素.

但是,您的类包含一个类型为unique_ptr实例的成员,该成员是不可复制的.这使得你的课程也不可复制.

此外,尽管unique_ptr是可移动的,但是您的类不是,因为编译器隐式生成移动构造函数会因显式定义的析构函数的存在而被抑制.如果不是这种情况(即,如果您明确定义了类的移动构造函数),则复制初始化将起作用(见8.5 / 15).

尝试更改WFactory的定义,如下所示:

class WFactory
{
public:
    WFactory(const int i)   : _w(new W1()) {}
    WFactory(const char* s) : _w(new W2()) {}
    WFactory(WFactory&& f) : _w(std::move(f._w)) {}
    ~WFactory() { _w.reset(nullptr); }
private:
    std::unique_ptr<Widget> _w;
};

int main()
{
    std::unique_ptr<Widget> a(new W1());
    WFactory wf[] { 4,"msg" };          // OK
}

原文地址:https://www.jb51.cc/c/114278.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐