标题
我们说
std::vector<MyObj*> ArrayOfPtr;
std::vector<MyObj const *> ArrayOfPtrToConstObj;
int main()
{
//I'd like to give ArrayOfPtr to another obj/function but not give it the right to modify the objects in it.
ArrayOfPtrToConstObj = ArrayOfPtr;
Function(ArrayOfPtrToConstObj)
}
为什么不能用C ++编写并且编译器自动理解,考虑到const不会改变逻辑(优化或任何东西)..?
有没有快速的方法从矢量1到矢量2而不必将/ while循环放到数组上并填充第二个?
答案 0 :(得分:1)
好吧,有人,某个地方将不得不循环。您可以使用vector::assign
:
ArrayOfPtrToConstObj.assign(ArrayOfPtr.begin(), ArrayOfPtr.end());
但是assign
仍然会循环播放。
首选的现代解决方案是传递一个const-iterator / pointer对,让用户使用它们,或使用像gsl::span
这样的视图类。这不需要复制任何内容,并且可以根据需要添加const
:
gsl::span<MyObj const*> spn(ArrayOfPtr.data(), ArrayOfPtr.size());
答案 1 :(得分:0)
vector2
是一种根本不同的类型。但是,如果您只想以vector1
方式查看const
的内部内容,我会为您提供解决方案。
我从gsl::span
开始,但不完全是这样。
template<class T>
struct span {
private:
T* b = 0;
T* e = 0;
public:
T* begin() const { return b; }
T* end() const { return e; }
T* data() const { return begin(); }
template<class U>
using compatible = std::enable_if_t< std::is_convertible< U*, T* >{} && sizeof(T)==sizeof(U), bool >;
template<class U,
compatible<U> =true
>
span( U* s, U* f ): b(s), e(f) {}
template<class U,
std::enable_if_t< std::is_convertible< U*, T* >{} && sizeof(T)==sizeof(U), bool > =true
>
span( U* s, std::size_t length ): span( s, s+length ) {}
// pointer semantics:
span()=default;
span(span const&)=default;
span& operator=(span const&)=default;
~span()=default;
std::size_t size() const{ return end()-begin(); }
bool empty() const{ return end()==begin(); }
T& front() const { return *begin(); }
T& back() const { return *(end()-1); }
// sub spans:
span without_front( std::size_t n=1 ) const {
n = (std::min)(n, size());
return {begin()+n, end()};
}
span without_back( std::size_t n=1 ) const {
n = (std::min)(n, size());
return {begin(), end()-n};
}
span only_front( std::size_t n=1 ) const {
n = (std::min)(n, size());
return {begin(), begin()+n};
}
span only_back( std::size_t n=1 ) const {
n = (std::min)(n, size());
return {end()-n, end()};
}
span sub( std::size_t start, std::size_t length ) const {
return without_front(start).only_front(length);
}
T& operator[](std::size_t I)const{ return begin()[I]; }
T& at(std::size_t I)const{
if (I>=size()) throw std::out_of_range{"index"};
return begin()[I];
}
std::vector<std::decay_t<T>> as_vector()const& {
return {begin(), end()};
}
std::vector<std::decay_t<T>> as_vector()&& {
return {std::make_move_iterator(begin()), std::make_move_iterator(end())};
}
template<class C,
compatible< std::decay_t< decltype( *std::declval<C&>().data() ) > > =true,
std::enable_if_t< !std::is_same<span, std::decay_t<C>>{}, bool > =true
>
span( C&& c ): span(c.data(), c.size()) {}
};
如果您不打算在上下文中更改vector
的长度,则span
是正确答案。
Live example进行了一些测试。
在这种情况下, Function
应该使用span< MyObj const*const >
,说明它只是想查看MyObj const
s的缓冲区。如果您愿意,可以存储此类型的范围,或者让隐式转换工作:
std::vector<MyObj*> ArrayOfPtr;
span<MyObj const*const> SpanOfPtrToConstObj;
int main()
{
//I'd like to give ArrayOfPtr to another obj/function but not give it the right to modify the objects in it.
SpanOfPtrToConstObj = ArrayOfPtr;
Function(SpanOfPtrToConstObj)
}
Function
无法修改向量的长度或其中的指针或指针指向的位置。