返回指针向量的类中的const方法

Ada*_*dam 9 c++ pointers stl const

说我有这个班:

#include <vector>
using namespace std;

class Bag
{
    vector<int*> items;

public:
    void addItem(int* i) 
    { 
        items.push_back(i); 
    }
    const vector<int*> getItems() const
    {
        return items;
    }
};
Run Code Online (Sandbox Code Playgroud)

问题是我想阻止参数项中指针指向的值的更改.但是使用从getItems我返回的向量允许更改指向的值.

现在,为了解决这个问题,我可以将参数项声明为,vector<const int*>但是我也无法更改我的类中的值.有没有其他方法来保护值但仍未在项目声明中使用const?

Bar*_*icz 5

正如@KerrekSB指出的那样,您需要重构结构,将元素的类型更改为const 元素:

std::vector<const int*> getItems() const { 
    return std::vector<const int*>(items.begin(), items.end());
}
Run Code Online (Sandbox Code Playgroud)

这里的构造vector<const int*>采用从隐式转换int*const int*.你不能只返回items这里,因为在T上vector<T>不变的.这直接意味着没有办法转换vector<int*>vector<const int*>仅仅通过类型转换.


解决你的评论:

这是唯一的方法吗?我觉得创建副本效率低下.

至于副本,它只复制指针数据,因此通常每个元素8个字节.对于指向较大结构的指针向量,它通常可以忽略不计,但对于ints 的向量,它确实是一个相当大的开销.

这带来了一个问题:为什么你首先存储指针?只需存储vector<int>,然后您就可以返回const&它.

  • 代码可以简化为`return {items.begin(),items.end()};` (2认同)
  • @Jinxed但是`std :: vector`在你想要添加一个项目而不是用一个大小进行初始化时,已经只支持`push_back`(或`emplace_back`). (2认同)

Tar*_*ama 5

如果您想避免复制并允许对std::vector元素进行只读访问,则可以提供const_iterator进入容器的函数:

class Bag
{
    vector<int*> items;

public:
    void addItem(int* i) 
    { 
        items.push_back(i); 
    }

    //could just be called begin if that gives the correct idea
    vector<int*>::const_iterator itemsBegin() const
    {
        return std::cbegin(items);
    }

    vector<int*>::const_iterator itemsEnd() const
    {
        return std::cend(items);   
    }
};
Run Code Online (Sandbox Code Playgroud)

然后,您将Bag使用该迭代器循环遍历内容,而不是获取整个vector项目.如果你提供的beginend功能,那么你甚至可以使用基于范围的for循环.