【问题标题】:Problem populating a vector with constructed struct objects用构造的结构对象填充向量的问题
【发布时间】:2020-03-23 22:53:52
【问题描述】:

我正在使用 ncurses 实现我的哲学家就餐问题的版本,但在初始化 Fork 对象的向量时遇到了问题。

#include <vector>
#include <mutex>
#include <ncurses.h>

...

struct Fork
{
    Fork(WINDOW *fork_window) : fork_window(fork_window) {}
    std::mutex m;
    WINDOW *fork_window;
};

std::vector<WINDOW *> fork_windows; // properly populated later
std::vector<Fork> forks;

...

for (int i = 0; i < num_of_phils; i++)
{
    forks.emplace_back(Fork(fork_windows[i]));
}

我想知道我的错误是什么(我对现代 C++ 没有那么丰富的经验)。 Fork 中的初始化列表是错误的还是 std::mutex 成员导致了问题?我以类似的方式成功填充了另一个向量,但另一个结构没有std::mutex 成员,只有WINDOW * 和三个ints

终端里的错误很长,说:

error: use of deleted function ‘Fork::Fork(Fork&&)’, 

...

note: ‘Fork::Fork(Fork&&)’ is implicitly deleted because the default definition would be ill-formed:

这是我第一次看到这样的错误,谷歌搜索也没有帮助,因为我在任何地方都没有找到类似的案例。

【问题讨论】:

  • 您正在尝试 emplacevector 中的对象,这需要移动构造函数,但您没有,因此您得到 error: use of deleted function ‘Fork::Fork(Fork&amp;&amp;)’。解决方案:创建移动构造函数
  • @nick std::mutex 不可移动,因此在按原样定义 Fork 的情况下无法创建移动构造函数。
  • @PaulSanders 假设他想要移动他从未声称想要移动的 mutex。如果mutex 用于某些内部事物(例如多个线程与Window* 混淆),则获得一个新的mutex 就可以了。
  • @PaulSanders 我并不是说您的解决方案是错误的或坏的,我只是说他的问题中没有任何内容表明他实际上 需要 移动那个@ 987654339@。这意味着实现移动构造函数将消除该错误。当然,在这种情况下有最佳实践,例如 5 规则,但这只会增加两个函数,其中一个他可能无论如何都需要(析构函数),他可能已经发布了一个 minimal 示例,其中为简单起见,已将其删除。
  • @PaulSanders 当然是:Fork(Fork&amp;&amp; f){ fork_window = f.fork_window; f.fork_window = nullptr; } 这会将 fork 窗口指针移到上方,将另一个指针设为空,并为新对象构造一个新的 mutex。复制运算符也是如此,但这看起来像是不应该被复制的类。

标签: c++ vector struct constructor initializer-list


【解决方案1】:

就目前情况而言,您不能拥有std::vector&lt;Fork&gt;,因为std::mutex 既不可复制也不可移动,这会隐式删除Fork 的复制和移动构造函数。

考虑改为使用std::vector&lt;std::unique_ptr&lt;Fork&gt;&gt;,如下所示:

#include <vector>
#include <mutex>
#include <memory>
#include <ncurses.h>

...

struct Fork
{
    Fork(WINDOW *fork_window) : fork_window(fork_window) {}
    std::mutex m;
    WINDOW *fork_window;
};

std::vector<WINDOW *> fork_windows; // properly populated later
std::vector<std::unique_ptr <Fork>> forks;

...

for (int i = 0; i < num_of_phils; i++)
{
    forks.emplace_back(new Fork(fork_windows[i]));
}

如果你愿意,你可以替换:

forks.emplace_back (new Fork (fork_windows [i]));

与:

forks.push_back (std::make_unique <Fork> (fork_windows [i]));

这主要是风格问题。


编辑:

修复代码的另一种方法是像这样声明Fork

struct Fork
{
    Fork(WINDOW *fork_window) : fork_window(fork_window) {}
    std::unique_ptr <std::mutex> m = std::make_unique <std::mutex> ();
    WINDOW *fork_window;
};

现在Fork 是可移动的(但不可复制)。

【讨论】:

    猜你喜欢
    • 2011-10-19
    • 1970-01-01
    • 2017-06-08
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多