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
}

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...