Array of unique_ptr to Array of pointers

huangapple go评论62阅读模式
英文:

Array of unique_ptr to Array of pointers

问题

array/vector of unique_ptr 在内部是否保证为原始指针的数组?在我的机器上似乎是这样,但标准是否保证?

我猜这个问题可以简化为:unique_ptr 是否始终作为仅包含原始指针的内存保留,或者可能会保存其他元数据。

基本上,我需要调用一个接受指针数组(实际上是双指针)的 C 函数。现在我可以传递一个 vector(vector::data)的 unique_ptr,并进行适当的转换,它可以正常工作。但我想确保在所有 C++ 实现上都会保持这样。

using item_ptr = unique_ptr<ITEM, ITEM_destructor>;
vector<item_ptr> items;
set_menu_items(m, reinterpret_cast<ITEM **>(items.data()));
英文:

Is array/vector of unique_ptr guaranteed to be array of raw pointers internally. It seems like it is so on my machine, but does the standard guarantee it?

I guess the question can be reduced to: Does unique_ptr always remain in memory as only a raw pointer or it's possible to have other metadata saved with it.

Basically i need to call a c function which takes an array of pointers (Actually it takes a double pointer obviously).
Now I can pass it a vector (vector::data) of unique_ptr with proper casting and it works fine. But I want to ensure that it will remain so on all the implementation of c++.

using item_ptr = unique_ptr&lt;ITEM, ITEM_destructor&gt;;
vector&lt;item_ptr&gt; items;
set_menu_items(m, reinterpret_cast&lt;ITEM **&gt;(items.data()));

答案1

得分: 2

以下是您要翻译的内容:

"Never keep double administration and do not use reinterpret_cast in your code! There should only be one source of information. This one source will be your std::vector&lt;std::unique_ptr&lt;Item&gt;&gt;. You only need a way to temporarily have a Item** to be able to pass this (as a view) to your set_menu_items call. For this example I assume the list of items will NOT change after the call to set_menu_items.

#include <vector>
#include <memory>
#include <iostream>
#include <string>

// demo item
struct Item
{
std::string name;
};

// function accepting only raw pointers
void set_menu_items(Item** items, const std::size_t number_of_items)
{
for (std::size_t n{0ul}; n < number_of_items; ++n)
{
Item* item_ptr = items[n];
std::cout << item_ptr->name << "\n";
}
};

// a struct to hold raw pointers for a while
class temporary_item_pointers_t final
{
public:
explicit temporary_item_pointers_t(const std::vector<std::unique_ptr<Item>>& item_ptrs)
{
for (const auto& ptr : item_ptrs)
{
m_item_ptrs.push_back(ptr.get());
}
}

Item** get() noexcept
{
    return m_item_ptrs.data();
}

auto size() const noexcept
{
    return m_item_ptrs.size();
}

private:
std::vector<Item*> m_item_ptrs;
};

auto make_items(const std::vector<std::string>& names)
{
std::vector<std::unique_ptr<Item>> items;
for (const auto& name : names)
{
items.emplace_back(std::make_unique<Item>(name));
}
}

int main()
{
auto items = make_items({ "item 1", "item 2", "item 3" });
temporary_item_pointers_t item_ptrs{ items };
set_menu_items(item_ptrs.get(), item_ptrs.size());

return 0;

}"

英文:

Never keep double administration and do not to use reinterpret_cast in your code!. There should only be one source of information. This one source will be your std::vector&lt;std::unique_ptr&lt;Item&gt;&gt;.
You only need a way to temporarily have a Item** to be able to pass this (as a view) to your set_menu_items call.

For this example I assume the list of items will NOT change after the call to set_menu_items.

#include &lt;vector&gt;
#include &lt;memory&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;


// demo item
struct Item
{
    std::string name;
};

// function accepting only raw pointers
void set_menu_items(Item** items, const std::size_t number_of_items)
{
    for (std::size_t n{0ul}; n &lt; number_of_items; ++n)
    {
        Item* item_ptr = items[n];
        std::cout &lt;&lt; item_ptr-&gt;name &lt;&lt; &quot;\n&quot;;
    }
};

// a struct to hold raw pointers for a while
class temporary_item_pointers_t final
{
public:
    explicit temporary_item_pointers_t(const std::vector&lt;std::unique_ptr&lt;Item&gt;&gt;&amp; item_ptrs)
    {
        for (const auto&amp; ptr : item_ptrs)
        {
            m_item_ptrs.push_back(ptr.get());
        }
    }

    Item** get() noexcept
    {
        return m_item_ptrs.data();
    }

    auto size() const noexcept
    {
        return m_item_ptrs.size();
    }

private:
    std::vector&lt;Item*&gt; m_item_ptrs;
};


auto make_items(const std::vector&lt;std::string&gt;&amp; names)
{
    std::vector&lt;std::unique_ptr&lt;Item&gt;&gt; items;
    for (const auto&amp; name : names)
    {
        items.emplace_back(std::make_unique&lt;Item&gt;(name));
    }
    return items;
}


int main()
{
    auto items = make_items({ &quot;item 1&quot;, &quot;item 2&quot;, &quot;item 3&quot; });
    temporary_item_pointers_t item_ptrs{ items };
    set_menu_items(item_ptrs.get(), item_ptrs.size());

    return 0;
}

huangapple
  • 本文由 发表于 2023年6月12日 11:51:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76453546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定