一类包含std::vector<int*>
外部代码需要只读到这个载体的访问,不应该能够修改内容(无论是指针或它们的内容)。 类内,这些值可以改变(例如double_values()
因此将其存储为一个std::vector<const int*>
是不可能的。
有没有办法返回std::vector<int*>
作为std::vector<const int*>
不进行复制? 这感觉就像应该有,因为常量是在编译时简单地操作该说些什么,不能进行修改。
代码:(与编译g++ -std=c++0x
)
class ReadOnlyAccess
{
public:
ReadOnlyAccess(const std::vector<int*> & int_ptrs_param):
int_ptrs(int_ptrs_param)
{
}
const std::vector<int*> & get_int_ptrs() const
{
return int_ptrs;
}
std::vector<const int*> safely_get_int_ptrs() const
{
// will not compile (too bad):
// return int_ptrs;
// need to copy entire vector
std::vector<const int*> result(int_ptrs.size());
for (int k=0; k<int_ptrs.size(); k++)
result[k] = int_ptrs[k];
return result;
}
void double_values()
{
for (int*p : int_ptrs)
*p *= 2;
}
void print() const
{
for (const int * p : int_ptrs)
std::cout << *p << " ";
std::cout << std::endl;
}
private:
std::vector<int*> int_ptrs;
};
int main() {
ReadOnlyAccess roa(std::vector<int*>{new int(10), new int(20), new int(100)});
std::vector<const int*> safe_int_ptrs = roa.safely_get_int_ptrs();
// does not compile (good)
// *safe_int_ptrs[0] = -100000;
roa.print();
const std::vector<int*> & int_ptrs = roa.get_int_ptrs();
// changes are made to the internal class values via the accessor! nooooo!
*int_ptrs[0] = -100000;
roa.print();
return 0;
}
如果你想保持常量指针反正返回载体将意味着一个副本。
然而,如果你的目标是提供一种方法,使用的值,而无需修改它们,或修改它的容器,那么访问者模式基于算法可能是一个很好的解决方案,尤其是现在,我们可以使用lambda表达式:
#include <vector>
#include <iostream>
class Data
{
public:
//...whatever needed to fill the values
// here we assume that Func is equivalent to std::function< void ( int )> or std::function< void (const int& ) > and can return anything that will be ignored here.
template< class Func >
void for_each_value( Func func ) const // read-only
{
for( const int* value : m_values ) // implicit conversion
{
func( *value ); // read-only reference (const &), or copy
// if func needs to work with the adress of the object, it still can by getting a reference to it and using & to get it's adress
}
}
void print() const
{
std::cout << "\nData values: \n";
for_each_value( []( const int value ) { std::cout << " "<< value << '\n'; } );
}
void count_values() const { return m_values.size(); }
private:
std::vector<int*> m_values;
};
int main()
{
Data data;
// ... whatever needed to fill the data
data.print();
std::vector<int> modified_values;
data.for_each_value( [&]( int value ) { modified_values.push_back( value + 42 ); } );
return 0;
}
如果你明白了,使用的值不同的方式可以降低到几半泛型算法,那么它会让你的代码更简单,让你保持你的结构内数据,而不是揭露它的胆量。
您可以通过自定义的迭代器提供了一个以常量的值。 一个简单的方法是使用boost::iterator
:
#include <boost/iterator/indirect_iterator.hpp>
class ReadOnlyAccess
{
// ...
typedef boost::indirect_iterator<const int* const*, const int> const_val_iter_type;
const_val_iter_type cval_begin() {
return it_t{const_cast<const int* const*>(&int_ptrs[0])};
}
}
int main() {
// ...
auto x = roa.cval_begin();
std::cout << x[0] <<' ' << x[1] << x[2] <<'\n';
// we can still access the pointers themselves via .base() member function:
for (int i=0; i<3; ++i)
assert(x.base()[i] == safe_int_ptrs[i]);
// the values are read-only, the following does not compile:
// x[0] = -1;
// **x.base() = -1;
// *x.base() = nullptr;
}
如果我们使用boost::indirect_iterator<typename std::vector<int*>::const_iterator, const int>
为const_val_iter_type
,我们可以修改经由尖值.base()
但(不直接像例如x[0] = -1
),所以这个解决方案是不一般。