我的算法需要std::vector
(称之为A
)。但是,我已经B
个N + 2
个条目,而我基本上想要的是传递B.data() + 2
,因此算法会从N
获取最后B
个条目。如果A
被修改,那么B
也是如此。
当使用double*
指针时,我非常清楚我应该如何制作它,但std::vector
s也可以这样做吗?我的意思是,矢量的好处是它为我处理内存,我现在想要的是禁止它(如果B
或A
被破坏,它们应该保持指向的数据不变)。
像这样:
std::vector< double > B({1,2,3,4,5});
std::vector< double > A(B.data() + 2, B.size() - 2);
// A and B share data now. A is 3, 4, 5
我知道通过使用一对迭代器可以更好地为此设计算法,但这不在我手中。
更新
(在评论中,有人希望看到签名,这里是)
nlopt::result nlopt::opt::optimize(std::vector<double> &x, double &opt_f);
然而,我的初衷是非常聪明,让算法在我的向量B
中优化direclty,所以我最终得到的是这样的:
std::vector< double > B(N + 2);
// do something with it here, like put initial values
std::vector< double > A( B.begin() + 2, B.end() );
optimize( A );
std::copy(A.begin(), A.end(), B.begin() + 2);
我真的不担心这种解决方法,我还在nlopt
的文档中读到,如果使用C ++接口而不是C语言接口,那么向量内部复制很多次。
但是,这个例子真的让我开始关注算法界面设计,并且值得投入一些时间浏览例如像range
等提升库。
答案 0 :(得分:7)
实际上,我在项目中遇到了类似的问题,这是我提出的解决方案:
#include <iterator>
#include <type_traits>
/** \brief Provides an interface to random accessible ranges
* \tparam RAIterator must be a random access iterator
*
* This class doesn't allocate any memory by itself and
* provides only an interface into the data of another
* container.
* \attention Keep in mind that although all methods are
* \c const, the returned RAIterator might not be a \c const_iterator
* at all. It is your responsibility to make sure that
* you don't invalidate the given range while working on it.
**/
template <class RAIterator>
class Slice
{
public:
//! Typedef for convenience when working with standard algorithms
typedef RAIterator iterator;
//! Alias to the iterator's reference type
typedef typename std::iterator_traits<RAIterator>::reference reference;
//! Creates the slice.
//! \param first, last a valid range
Slice(RAIterator first, RAIterator last) : first(first), last(last){}
//! Creates the slice.
//! \param first iterator to the first element
//! \param length of the range [first, first+length)
//! \remark if length is negative, an empty slice is assumed.
Slice(RAIterator first, int length) :
first(first),
last( length > 0 ? first + length : first)
{}
//! The default constructor is deleted, as it would resemble an empty slice
Slice() = delete;
///@{
//! \brief Defaulted construcors.
Slice(const Slice&) = default;
Slice(Slice&&) = default;
Slice& operator=(const Slice&)= default;
Slice& operator=(Slice&&)= default;
/**@}*/
//! Returns an iterator to the begin of the range
RAIterator begin() const{ return first; }
//! Returns an iterator to the end of the range
RAIterator end() const{ return last; }
//! Returns the size of the slice.
typename std::iterator_traits<RAIterator>::difference_type size() const{
return std::distance(first, last);
}
//! Provides random access for the values interfaced by Slice
reference operator[](size_t index) const { return first[index]; }
private:
RAIterator first; //!< begin of the range
RAIterator last; //!< end of the range
};
/** \brief Creates a slice from the given range
* \tparam RAIterator should be an random access iterator
* \returns a slice [first,last)
* \param first, last is the range
**/
template <class RAIterator>
Slice<RAIterator> make_slice(RAIterator first, RAIterator last){
return Slice<RAIterator>(first, last);
}
现在您可以像示例一样使用Slice
:
std::vector< double > B({1,2,3,4,5});
Slice A(B.begin() + 2, B.size() - 2);
A[0] = 5;
// B == {1,2,5,4,5}
编辑:如果您想要更成熟的切片,请尽可能使用boost::adaptors::slice
。
答案 1 :(得分:0)
只有两个想法。
如果函数接受对std :: vector的引用 - 尝试使用std :: vector作为基类创建类。
尝试使用allocator,它是std :: vector的第二个模板参数。有了它,您可以根据需要分配或只使用已分配的内存。 http://www.cplusplus.com/reference/vector/vector/ http://www.cplusplus.com/reference/vector/vector/get_allocator/
答案 2 :(得分:0)
只是疯狂的回答。
我考虑使用vector
shared_ptr<double>
,其中shared_ptr
指向个人double
。因此它看起来很丑陋并且可能很痛苦,那些vectors
将共享包含doubles
的内存。