英文:
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<ITEM, ITEM_destructor>;
vector<item_ptr> items;
set_menu_items(m, reinterpret_cast<ITEM **>(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<std::unique_ptr<Item>>
. 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<std::unique_ptr<Item>>
.
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));
}
return items;
}
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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论