如何创建结构向量并稍后初始化它们

Posted

技术标签:

【中文标题】如何创建结构向量并稍后初始化它们【英文标题】:How to create a vector of structs and initialize them later 【发布时间】:2014-11-28 10:57:42 【问题描述】:

为了更容易处理,我想创建一个自定义元素的向量,之后我可以通过A[0] 等轻松访问。问题是每个元素都有一个非空的构造函数,即我不会写

elem A;

我必须写

elem A(int a, int b, int c);

在创建期间使用 a、b、c 固定值。但这对我来说是不可能的,因为我在运行时获取了这些元素的值。 那么,有没有办法做这样的事情:

Vector<elem> A;
elem B(int a, int b, int c);
A.push_back(B);

如果是,怎么做? 作为解释:Vector 可以是std::vectorQVector,但它们都会导致一个问题,要么在编译时崩溃,要么在运行时崩溃。 编辑: 完整代码:

#ifndef DPC_H
#define DPC_H
#include "../BlackLib/v2_0/BlackGPIO.h"
#include <QVector>


class DPC

private:
    QVector<BlackLib::BlackGPIO> A;
public:
    DPC();
    ~DPC();
;

#endif // DPC_H


#include "dpc.h"


    DPC::DPC()
    
        BlackLib::BlackGPIO Pin(BlackLib::BlackGPIO(BlackLib::GPIO_32, BlackLib::input));
        /*DPC::A[0] = new */A.push_back(Pin);
        A.push_back(Pin);
        /*DPC::A[1] = new B*/A.push_back(BlackLib::BlackGPIO(BlackLib::GPIO_33, BlackLib::input));

    

BlackLib 是来自 https://github.com/yigityuce/BlackLib 的 BBB 引脚扩展的数据类型

解决方案: 使用std::vector&lt;std::unique_ptr&lt;BlackLib::BlackGPIO&gt; &gt; A;

【问题讨论】:

是的,我收到一条错误消息,告诉我“候选人需要 3 个参数,得到 0”。 在哪段代码中? Vector&lt;elem&gt; A; 这不应该要求 elem 是 DefaultConstructible。演示:ideone.com/159D9Q 这不是“完整代码”,见MCVE 【参考方案1】:

实际上,几乎完全按照您的写作方式。你可以这样做

#include <vector>

...

std::vector<B> A;
B foo(a, b, c);
A.push_back(foo);

或者,如果您有一个了解 C++11 的足够新的编译器,

#include <vector>

...

std::vector<B> A;
A.emplace_back(a, b, c);

后者保存一个副本(对象直接在向量内部构造),因此更好™。尽管正如@JonathanWakely 在 cmets 中指出的那样,必须注意维护 emplace_back 的异常安全性,因为

std::vector<std::unique_ptr<B> > vec;

vec.emplace_back(new B); // is not exception-safe if the vector has to 
                         // relocate and might throw bad_alloc, in which case
                         // the newly allocated foo object is leaked because
                         // no one is responsible for cleaning it up.

vec.push_back(new B);    // does not compile

这在std::vector&lt;std::unique_ptr&lt;...&gt;&gt; 的情况下很容易解决:

vec.emplace_back(std::make_unique<B>());     // C++14
vec.emplace_back(std::unique_ptr<B>(new B)); // C++11

// these also work and do the same thing with push_back

...但你必须记住这样做。

【讨论】:

我对 BlackLib 不熟悉,但粗略地看一下代码让我相信它不适合这个用例。 BlackGPIO 类拥有一个指向堆数据的裸指针,但没有用户定义的复制或移动构造函数。这后来导致双重释放。确实这应该在 BlackLib 中修复,但作为一种解决方法,您可以使用 std::vector&lt;std::unique_ptr&lt;BlackLib::BlackGPIO&gt; &gt; 并执行 A.emplace_back(new BlackLib::BlackGPIO(...)); 这意味着我必须添加自己的构造函数? 我之后是否必须释放一些东西(因为使用新的?)我对 unique_ptr 不太熟悉,因此我问(仅使用向量时我不必释放一些东西)。 std::unique_ptr 为您做到这一点——这是它在生活中的唯一目的。 @Wintermute, emplace_back(new ...) 如果向量尝试重新分配并抛出 bad_alloc,则不是异常安全的@【参考方案2】:

那么,有没有办法做这样的事情:

 vector<elem> A;
 elem B(int a, int b, int c);
 A.push_back(B);

如果是,怎么做?

是的。有几种可能性。首先,检查 emplace_back。类似于push back,只是参数直接传给了被持有对象的构造函数(完美转发):

vector<elem> A;
A.emplace_back(a, b, c); // for an existing elem::elem(int a, int b, int c)

你也可以依赖elem的拷贝构造函数,在一个模型之后构造n个元素:

elem model a, b, c ;
vector<elem> A 10, model ; // create 10 elements equal to model

【讨论】:

以上是关于如何创建结构向量并稍后初始化它们的主要内容,如果未能解决你的问题,请参考以下文章

如何在初始化时设置结构的向量成员的大小?

使用 memset 初始化包含数组的结构向量

如何匹配包含 lvar 的地图?

c ++初始化结构向量的正确方法

我如何使用包含 vector<Mat> 的结构向量

编译多个 C++,得到未初始化的向量