C++ 如何将指向指针列表的私有指针作为常量返回?
我有一个指向指针列表的指针,作为私有变量。我还有一个getter返回指向列表的指针。我需要保护它不受更改 我找不到如何使用reinterpret\u cast或const\u castC++ 如何将指向指针列表的私有指针作为常量返回?,c++,constants,smart-pointers,private-members,container-data-type,C++,Constants,Smart Pointers,Private Members,Container Data Type,我有一个指向指针列表的指针,作为私有变量。我还有一个getter返回指向列表的指针。我需要保护它不受更改 我找不到如何使用reinterpret\u cast或const\u cast class typeA{ shared_ptr<list<shared_ptr<typeB>>> l; public: shared_ptr<list<shared_ptr<const typeB>>> getList(){re
class typeA{
shared_ptr<list<shared_ptr<typeB>>> l;
public:
shared_ptr<list<shared_ptr<const typeB>>> getList(){return (l);};
};
或者至少像:
shared_ptr<list<shared_ptr<const typeB>>>
shared\u ptr
?
引用而不是指针不是一个选项。将l
声明为shared\u ptr
也不是需要的解决方案
编辑:不再使用“int”
这似乎不可能完全符合我的要求,但建议的解决方案是好的。是的,复制指针是可以接受的
我的错是我没有马上打B型。我知道引用比指针有一些优点,但我希望有类似的解决方案。当您将指向nonst的指针转换为指向const的指针时,您有两个指针。此外,指向nonconst的指针列表与指向const的指针列表是完全不同的类型 因此,如果您想要返回指向const的指针列表的指针,那么您必须拥有指向const的指针列表。但你没有这样的清单。您有一个指向nonconst的指针列表,这些列表类型是不可相互转换的 当然,您可以将指向nonconst的指针转换为指向const的指针列表,但您必须了解它是一个单独的列表。指向前一种类型的指针不能指向后一种类型 因此,下面是一个转换列表的示例(我没有测试,可能包含打字错误或错误): 请注意,虽然列表是分开的,但其中的指针仍然指向相同的整数
作为一个旁注,请考虑一个<代码> int >代码>对象的共享所有权是否对程序有意义——我假设这是一个简化例子。
还要重新考虑“引用而不是指针不是一个选项”是否是一个合理的要求。您可以从原始列表中创建一个新的
常量int列表,并返回:
std::shared_ptr<std::list<std::shared_ptr<const int>>> getList(){
return std::make_shared<std::list<std::shared_ptr<const int>>>(l->begin(), l->end());
}
你的问题完全在于
但我不想混合引用和指针。只有指针更容易、更干净
你在这里发现,这种说法是错误的。列表
可以绑定常量列表&
引用,并且列表的任何成员都不允许对类型b
对象进行任何修改
class typeA {
std::vector<typeB> l;
public:
const std::vector<typeB> & getList() const { return l; };
};
另一种选择是,您可以将您的std::shared_ptr
s包装成类似的格式,然后直接返回它们。模板的问题是任何
template <typename T>
class C { };
如果您使用向量而不是列表,我将提供一个索引运算符:
shared_ptr<typeB /* const or not? */> operator[](size_t index);
请看一个完整的示例–但是要注意,std::iterator
已被弃用,因此您需要自己实现类型特征
如果在内部使用std::vector
,则要使用的迭代器标记将是std::bidirectional\u iterator\u tag
或random\u access\u iterator\u tag
(continuous\u iterator\u tag
)
现在重要的是如何实现所需的两个操作符:
std::shared_ptr<int const> TypeA::iterator::operator*()
{
return std::shared_ptr<int const>(*i);
}
std::shared_ptr<int const> TypeA::iterator::operator->()
{
return *this;
}
std::shared\u ptr TypeA::迭代器::运算符*()
{
返回std::shared_ptr(*i);
}
std::shared_ptr TypeA::迭代器::运算符->()
{
归还*这个;
}
其他操作符只是将操作转发给内部迭代器(增量、减量(如果可用)、比较等)
我并不认为这是圣杯,这是你在任何情况下都需要遵循的道路。但这是一个值得考虑的有价值的选择… < P>你这里有一个非常复杂的结构:
shared_ptr<list<shared_ptr<typeB>>> l;
shared\u ptr l;
这是三个级别的间接寻址,其中两个级别具有引用计数生存期管理,第三个级别是容器(在该级别上不是内存连续的)
当然,鉴于这种复杂的结构,将其转换为另一种类型并不容易:
shared_ptr<list<shared_ptr<const typeB>>>
shared\u ptr
注意,std::list
和std::list
是标准库设计中两种不同的类型。当您想向容器传递非修改句柄时,通常应该使用const\u迭代器s.
在您的例子中,在列表的顶部有一个共享的\u ptr
,因此如果您想要引用计数行为,就不能使用迭代器
在这一点上出现了一个问题:你真的想要这种行为吗
- 您是否希望出现这样一种情况:您的
typeA
实例被销毁,但仍有其他一些typeA
实例使用相同的容器
- 您是否希望所有共享容器的
typeA
实例都被销毁,但在运行时的其他位置仍有一些对该容器的引用
- 您是否期望容器本身被破坏,但仍然有一些对某些元素的引用
- 您是否有任何理由使用
std::list
而不是更传统的容器来存储共享指针李>
如果您对所有要点的回答都是“是”,那么为了实现您的目标,您可能必须设计一个新类,它将充当共享的\u ptr
的持有者,同时只提供对元素的const
访问
如果你的答案是否定的,考虑重新设计<代码> L>代码>类型。我建议从std::vector开始,然后逐个添加必要的修改
我更好奇的是为什么你有一个指向容器的指针?这方面的用例是什么?为什么有一个指向int
的指针容器?这方面的用例是什么?只列出怎么样?为什么这不是一个想要的解决方案?@FantasticMrFox除非有特殊要求,std::vector
在我看来更可取。我想你应该
class typeA {
std::vector<typeB> l;
public:
const std::vector<typeB> & getList() const { return l; };
};
std::shared_ptr<const typeB> add_const(std::shared_ptr<typeB> ptr)
{
return { ptr, ptr.get() };
}
class typeA {
std::vector<std::shared_ptr<typeB>> l;
public:
auto getList() const { return l | std::ranges::transform(add_const); };
};
template <typename T>
class C { };
class typeA
{
// wondering pretty much why you need a shared pointer here at all!
// (instead of directly aggregating the list)
shared_ptr<list<shared_ptr<typeB>>> l;
public:
shared_ptr<list<shared_ptr<typeB>>>::const_iterator begin() { return l->begin(); }
shared_ptr<list<shared_ptr<typeB>>>::const_iterator end() { return l->end(); }
};
shared_ptr<typeB /* const or not? */> operator[](size_t index);
class TypeA
{
public:
class iterator
{
std::list<std::shared_ptr<int>>::iterator i;
public:
// implementation as needed: operators, type traits, etc.
};
};
std::shared_ptr<int const> TypeA::iterator::operator*()
{
return std::shared_ptr<int const>(*i);
}
std::shared_ptr<int const> TypeA::iterator::operator->()
{
return *this;
}
shared_ptr<list<shared_ptr<typeB>>> l;
shared_ptr<list<shared_ptr<const typeB>>>