use*_*303 12 c++ arrays const stdvector dynamic-arrays
在C++中,我希望分配一个固定大小(但在运行时确定的大小)std :: vector然后写入此向量中的元素.这是我正在使用的代码:
int b = 30;
const std::vector<int> test(b);
int &a = test[3];
Run Code Online (Sandbox Code Playgroud)
但是,这给了我一个编译器(MSVC 2010 Pro)错误:
错误C2440:'initializing':无法从'const int'转换为'int&'.转换失去限定符.
我对const的理解是它使一个类的所有成员变量保持不变.例如,以下工作正常:
class myvec
{
public:
myvec(int num) : ptr_m(new int[num]) {};
~myvec() { delete ptr_m; }
void resize(int num) { delete ptr_m; ptr_m = new int[num]; }
int & operator[] (int i) const { return ptr_m[i]; }
int *ptr_m;
};
const myvec test(30);
int &a = test[3]; // This is fine, as desired
test.resize(10); // Error here, as expected
Run Code Online (Sandbox Code Playgroud)
因此,似乎std :: vector将容器的常量传播到向量的元素,这看起来很奇怪,因为如果我希望元素是const,我会使用它std::vector<const int>.因此,这是std :: vector的一个缺点.
在任何情况下,如何创建一个std :: vector,其大小在构造后不能更改,但其元素可以写入?
Tem*_*Rex 13
如果不编写自己的包装类,这是不可能的.如果你想用一个简单的std::vector,你必须通过不使用成员函数依靠自律insert(),push_back()或者emplace_back(),直接或间接地(例如,通过back_inserter).
请注意,目前有关新C++ 14标准的动态数组的建议:
[...]我们建议为数组定义一个新的设施,其中元素的数量在结构上被绑定.我们将这些动态数组称为dynarray.
该提议实际上附带了一个参考实现,您可以在自己的代码中使用(确保namespace std暂时改为其他内容).
namespace std {
template< class T >
struct dynarray
{
// types:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
// fields:
private:
T* store;
size_type count;
// helper functions:
void check(size_type n)
{ if ( n >= count ) throw out_of_range("dynarray"); }
T* alloc(size_type n)
{ if ( n > std::numeric_limits<size_type>::max()/sizeof(T) )
throw std::bad_array_length();
return reinterpret_cast<T*>( new char[ n*sizeof(T) ] ); }
public:
// construct and destruct:
dynarray() = delete;
const dynarray operator=(const dynarray&) = delete;
explicit dynarray(size_type c)
: store( alloc( c ) ), count( c )
{ size_type i;
try {
for ( size_type i = 0; i < count; ++i )
new (store+i) T;
} catch ( ... ) {
for ( ; i > 0; --i )
(store+(i-1))->~T();
throw;
} }
dynarray(const dynarray& d)
: store( alloc( d.count ) ), count( d.count )
{ try { uninitialized_copy( d.begin(), d.end(), begin() ); }
catch ( ... ) { delete store; throw; } }
~dynarray()
{ for ( size_type i = 0; i < count; ++i )
(store+i)->~T();
delete[] store; }
// iterators:
iterator begin() { return store; }
const_iterator begin() const { return store; }
const_iterator cbegin() const { return store; }
iterator end() { return store + count; }
const_iterator end() const { return store + count; }
const_iterator cend() const { return store + count; }
reverse_iterator rbegin()
{ return reverse_iterator(end()); }
const_reverse_iterator rbegin() const
{ return reverse_iterator(end()); }
reverse_iterator rend()
{ return reverse_iterator(begin()); }
const_reverse_iterator rend() const
{ return reverse_iterator(begin()); }
// capacity:
size_type size() const { return count; }
size_type max_size() const { return count; }
bool empty() const { return count == 0; }
// element access:
reference operator[](size_type n) { return store[n]; }
const_reference operator[](size_type n) const { return store[n]; }
reference front() { return store[0]; }
const_reference front() const { return store[0]; }
reference back() { return store[count-1]; }
const_reference back() const { return store[count-1]; }
const_reference at(size_type n) const { check(n); return store[n]; }
reference at(size_type n) { check(n); return store[n]; }
// data access:
T* data() { return store; }
const T* data() const { return store; }
};
} // namespace std
Run Code Online (Sandbox Code Playgroud)