Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将指向指针列表的私有指针作为常量返回?_C++_Constants_Smart Pointers_Private Members_Container Data Type - Fatal编程技术网

C++ 如何将指向指针列表的私有指针作为常量返回?

C++ 如何将指向指针列表的私有指针作为常量返回?,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

我有一个指向指针列表的指针,作为私有变量。我还有一个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(){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>>>