gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:14:31 24 4
gpt4 key购买 nike

全部,

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

$ uname -a

Linux .. 3.5.0-21-generic#32-Ubuntu SMP 2012 年 12 月 11 日星期二 18:51:59 UTC 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<> 的表达能力与裸 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 的回复,以下代码不会抑制隐式移动构造函数:

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() 中对 wf[] 使用 c++11 风格的迭代会返回 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 的实例,它是不可复制的。这也使您的类(class)不可复制。

此外,尽管 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++ - std::unique_ptr 删除函数,initializer_list - 驱动分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15032501/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com