gpt4 book ai didi

c++ - 两个 std::vectors 指向几乎相同的数据,这可能吗

转载 作者:可可西里 更新时间:2023-11-01 15:22:33 24 4
gpt4 key购买 nike

我有一个算法需要一个std::vector(称之为A)。但是,我已经有了带有 N + 2 条目的 B,我基本上想要传递 B.data() + 2,所以算法从 B 中获取最后的 N 条目。如果 A 被修改,那么 B 也会被修改。

当使用 double* 指针时,我应该如何做到这一点是非常清楚的,但这是否也可以用 std::vector 实现?我的意思是, vector 的好处是它可以为我处理内存,我现在想要的是禁止它(如果 BA 被销毁,它们应该保持指向的数据不变)。

像这样:

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);

然而,我的初衷是非常聪明,让算法直接优化我的 vector B,所以我最终得到的结果是这样的:

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++ 接口(interface)而不是 C 接口(interface), vector 无论如何都是内部拷贝很多次.

但是,这个例子确实让我对算法界面设计大开眼界,值得花一些时间浏览例如boost 库,如 range 等。

最佳答案

其实我在一个项目中遇到过类似的问题,这是我想出的解决方案:

#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如果可能的话。

关于c++ - 两个 std::vectors 指向几乎相同的数据,这可能吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19536306/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com