简体   繁体   English

从指针有条件地初始化 std::vector

[英]Conditionally initialize std::vector from pointer

I am interfacing with some C++ code that has a method providing a pointer and object size (some proprietary library that I can't change).我正在与一些 C++ 代码交互,该代码具有提供指针和 object 大小的方法(一些我无法更改的专有库)。 The interface looks something like this:界面看起来像这样:

float *arrayPtr();
int arraySize();

I have a class that needs to copy this to a vector (in order to extend its lifetime).我有一个 class 需要将其复制到向量中(以延长其寿命)。 In the scenario where this pointer is not a nullptr, the constructor is fairly simple (I need to copy the data to extend its lifetime):在此指针不是 nullptr 的情况下,构造函数相当简单(我需要复制数据以延长其生命周期):

struct A {
    std::vector<float> vec;
    A(float *ptr, int size) : vec( ptr, std::next(ptr, size) ) {}
}

I am, however, a little unsure of how best to handle the initialization when ptr is a nullptr .但是,我有点不确定当ptrnullptr时如何最好地处理初始化。 I could default initialize, and then move everything to the constructor body, but that feels quite inefficient:我可以默认初始化,然后将所有内容移至构造函数主体,但这感觉效率很低:

A(float *ptr, int size) {
    if (ptr) {
        vec = std::vector<float>( ptr, std::next(ptr, size));
    }
}

Are there any other alternatives?还有其他选择吗?

When ptr is a nullptr , I would like the vector to just be default initialized to an empty vector.ptrnullptr时,我希望将向量默认初始化为空向量。

EDIT:编辑:

It just occurred to me that I should probably be doing this:我突然想到我可能应该这样做:

A(float *ptr, int size) : vec( ptr ? std::vector<float>(ptr, std::next(ptr, size)) : std::vector<float>() ) {}

But perhaps there is a better form??但也许有更好的形式?

This is not necessarily "better" (actually I think your original code is fine, since there is not really any cost to default initialization of a vector), but when you need to perform some logic for an initializer you can use a helper function:这不一定“更好”(实际上我认为您的原始代码很好,因为向量的默认初始化实际上并没有任何成本),但是当您需要为初始化程序执行一些逻辑时,您可以使用帮助程序 function:

struct A {
    std::vector<float> vec;
    A(float *ptr, int size) : vec( make_A_vector(ptr, size) ) {}

private:  
    static std::vector<float> make_A_vector(float const *begin, int size)
    {
        if ( size < 0 || (size > 0 && !begin) )
             throw std::runtime_error("invalid array length for A");

        if ( size == 0 )
             return {};

        return std::vector<float>(begin, begin + size);
   }
};

Another common design is to keep your class simple and have construction logic entirely in a free function:另一个常见的设计是让您的 class 保持简单,并在免费的 function 中完全具有构造逻辑:

struct A
{
    std::vector<float> vec;
};

inline A make_A(float const *ptr, int size)
{
     // sanity check omitted for brevity
     if ( size == 0 )
         return A{};

     return A{ std::vector<float>(ptr, ptr + size) };
}

It's an experience-based judgement call as to what would be overkill and what would be aesthetic:)这是一个基于经验的判断,关于什么是矫枉过正,什么是审美:)

Researching what std::next and the ctor of std::vector is doing.研究std::nextstd::vector的 ctor 正在做什么。 your first try works just fine.你的第一次尝试效果很好。 ONLY and ONLY if your size is reliably 0 , when your pointer is a nullptr .仅当您的size可靠地为0时,当您的指针为nullptr时。

std::next(it, n)

it - Iterator to base position. it - 基于 position 的迭代器。 ForwardIterator shall be at least a forward iterator. ForwardIterator 应至少是一个前向迭代器。

n - Number of element positions offset (1 by default). n - 元素位置偏移的数量(默认为 1)。 This shall only be negative for random-access and bidirectional iterators.这仅对随机访问和双向迭代器是负面的。 difference_type is the numerical type that represents distances between iterators of the ForwardIterator type. difference_type 是表示 ForwardIterator 类型的迭代器之间距离的数值类型。

If you are assured, your given size is 0 , when you get a nullptr , std::next returns the same position as your pointer points to.如果您放心,您的给定大小为0 ,当您获得nullptr时, std::next返回与指针指向的相同 position 。

std::vector

You use this ctor:你使用这个ctor:

Constructs the container with the contents of the range [first, last).使用范围 [first, last) 的内容构造容器。

If your first and last are the same, you get an empty std::vector .如果你的firstlast相同,你会得到一个空的std::vector So the nullptr is never a problem.所以nullptr从来都不是问题。


Regardless this findings.不管这个发现。 you should ALWAYS check for nullptr 's.你应该总是检查nullptr的。 For the sake of defensive programming - ALL INPUT IS EVIL!为了防御性编程 - 所有输入都是邪恶的!


You mentioned, the library you get is known for being error prone.您提到过,您获得的库以容易出错而闻名。 Please save yourself much troubles and check every parameter you get out of it of integrity.请省去很多麻烦,并检查您从中获得的每个参数的完整性。


One comment on your worries that your implementation would perform any worse then an other.一条评论是关于您担心您的实施会比其他实施更差的评论。 Check those implementations in an loop with thousands or millions of iterations.在具有数千或数百万次迭代的loop中检查这些实现。 Then you can make an prediction if it effects you.然后,如果它影响到你,你就可以做出预测。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM