n
要素を持つ_std::vector
_があります。ここで、最後の_n-1
_要素を持つベクトルへのポインターを関数に渡す必要があります。
たとえば、私の_vector<int> foo
_には_(5,2,6,87,251)
_が含まれます。関数は_vector<int>*
_を取り、_(2,6,87,251)
_へのポインターを渡します。
イテレータ++foo.begin()
を(安全に)取得し、ポインタに変換して関数に渡すことはできますか?または_&foo[1]
_を使用しますか?
PDATE:人々は、ポインターではなくイテレーターを使用するように関数を変更することを提案しています。私が言及した関数は_unordered_set<std::vector*>
_のfind
関数なので、私の状況ではそれは不可能のようです。したがって、その場合、foo
から_n-1
_要素を新しいベクトルにコピーし、その唯一のオプションへのポインターでfind
を呼び出しますか?非常に非効率的です!特に多くのサブセット(最後の_n-1
_、次に_n-2
_などの要素をクエリし、_unordered_set
_にあるかどうかを確認する必要があるため、これは画家のシュレミエルに似ています。
私が言及した関数は_
unordered_set<std::vector*>
_の検索関数なので、私の状況ではそれは不可能のようです。
カスタムハッシュ/述語関数オブジェクトを使用していますか?そうでない場合は、unordered_set<std::vector<int>*>::find()
に、検索する正確なベクトルへのポインターを渡す必要があります。同じ内容の別のベクターへのポインターは機能しません。控えめに言っても、これは検索にはあまり役に立ちません。
_unordered_set<std::vector<int> >
_を使用すると、値でルックアップを実行できるため、より適切です。 hash
には_vector<int>
_の専門知識がないため、カスタムハッシュ関数オブジェクトも必要になると思います。
いずれにしても、他の人が説明したように、ベクターの中央へのポインターはそれ自体がベクターではありません。内容をコピーしないと、反復子をベクターへのポインターに変換できません。
ここでは、反復子useの対応するポインタへの参照を取得しています。
例:
string my_str= "hello world";
string::iterator it(my_str.begin());
char* pointer_inside_buffer=&(*it); //<--
[通知演算子*はreferenceを返すため、参照に対して&を実行するとアドレスが表示されます]。
可能であれば、関数を変更して、要素への反復子または新しいベクトル(変更されていない場合)を取得することをお勧めします。
配列の格納方法を知っているので、配列でこの種のことを行うことができますが、ベクトルで同じことを行うのはおそらく悪い考えです。 &foo[1]
にはタイプvector<int>*
がありません。
また、STLの実装はオンラインで利用できますが、通常、抽象化の内部構造に依存しようとするのは危険です。
ベクターは、その要素の完全な所有権を持つコンテナーです。 1つのベクトルは、constビューであっても、別のベクトルの部分ビューを保持できません。これが根本的な原因です。
それが必要な場合は、データに対するweak_ptrのビューを持つ独自のコンテナーを作成するか、範囲を確認します。ペアのイテレーター(ポインターでさえベクターへのイテレーターとして機能します)または、さらに良いことに、かなりシームレスに機能するboost :: iterator_range。
コードのテンプレート化可能性に依存します。 cppでコードを非表示にする必要がある場合は、std :: pairを使用します。
あなたの関数は_vector<int>*
_を取るべきではありません;必要に応じて_vector<int>::iterator
_または_vector<int>::const_iterator
_を取る必要があります。次に、foo.begin() + 1
を渡すだけです。
あなたの質問に対する直接的な答えはイエスです。 fooがベクトルの場合、これを行うことができます:&foo [1]。
ただし、標準ではベクターは連続メモリを使用してストレージを実装すると言われているため、これはベクターに対してのみ機能します。
しかし、表現力が高いため、未加工のポインタの代わりにイテレータを渡すことができます(おそらくそうすべきです)。イテレータを渡しても、ベクトルのコピーは作成されません。
たとえば、
vector<int> foo
には(5,2,6,87,251)が含まれます。関数はvector<int>*
を受け取り、(2,6,87,251)へのポインターを渡します。
vector<int>
へのポインターは、ベクトルの要素へのポインターとまったく同じものではありません。
これを行うには、ポインタを渡す要素のみを含む新しいvector<int>
を作成する必要があります。何かのようなもの:
vector<int> tempVector( foo.begin()+1, foo.end());
// now you can pass &tempVector to your function
ただし、関数がarray intへのポインターを取る場合は、&foo[1]
を渡すことができます。
つかいます - vector::front
、最もポータブルなソリューションである必要があります。 char ptrを必要とする固定APIとインターフェースをとるときにこれを使用しました。例:
void funcThatTakesCharPtr(char* start, size_t size);
...
void myFunc(vector<char>& myVec)
{
// Get a pointer to the front element of my vector:
char* myDataPtr = &(myVec.front());
// Pass that pointer to my external API:
funcThatTakesCharPtr(myDataPtr, myVec.size());
}
イテレーターをポインターに変換する安全なバージョン(意味に関係なく正確に何を意味するか)と安全で、イテレーターを逆参照し、end()
/otherに起因する可能性のある例外/エラーを引き起こす心配がない状況
#include <iostream>
#include <vector>
#include <string.h>
int main()
{
std::vector<int> vec;
char itPtr[25];
long long itPtrDec;
std::vector<int>::iterator it = vec.begin();
memset(&itPtr, 0, 25);
sprintf(itPtr, "%llu", it);
itPtrDec = atoll(itPtr);
printf("it = 0x%X\n", itPtrDec);
vec.Push_back(123);
it = vec.begin();
memset(&itPtr, 0, 25);
sprintf(itPtr, "%llu", it);
itPtrDec = atoll(itPtr);
printf("it = 0x%X\n", itPtrDec);
}
のようなものを印刷します
it = 0x0
it = 0x2202E10
それは信じられないほどハック的な方法ですが、必要な場合は仕事をします。コンパイラの警告が表示されますが、本当に気になる場合は、#pragma
で削除できます
私はこれをテストしていませんが、代わりにイテレーターのペアのセットを使用できますか?各反復子ペアは、シーケンスベクトルの開始反復子と終了反復子を表します。例えば。:
typedef std::vector<int> Seq;
typedef std::pair<Seq::const_iterator, Seq::const_iterator> SeqRange;
bool operator< (const SeqRange& lhs, const SeqRange& rhs)
{
Seq::const_iterator lhsNext = lhs.first;
Seq::const_iterator rhsNext = rhs.first;
while (lhsNext != lhs.second && rhsNext != rhs.second)
if (*lhsNext < *rhsNext)
return true;
else if (*lhsNext > *rhsNext)
return false;
return false;
}
typedef std::set<SeqRange, std::less<SeqRange> > SeqSet;
Seq sequences;
void test (const SeqSet& seqSet, const SeqRange& seq)
{
bool find = seqSet.find (seq) != seqSet.end ();
bool find2 = seqSet.find (SeqRange (seq.first + 1, seq.second)) != seqSet.end ();
}
明らかに、ベクターは以前のように他の場所に保持する必要があります。また、シーケンスベクトルが変更された場合、イテレータが変更された可能性があるため、セット内のエントリを削除して再追加する必要があります。
ジョン
関数が本当にvector<int> *
(ベクターへのポインター)をとる場合、&foo
を渡す必要があります。これはベクターへのポインターになるためです。明らかにそれは単にあなたの問題を解決するものではありませんが、イテレータのアドレスにあるメモリは有効なベクトルを直接アドレスしないので、イテレータを直接ベクトルに変換することはできません。
vector constructor :を呼び出すことで、新しいベクターを作成できます。
template <class InputIterator> vector(InputIterator, InputIterator)
これは、2つの反復子の間で要素をコピーすることにより、新しいベクトルを構築します。おおよそ次のように使用します。
bar(std::vector<int>(foo.begin()+1, foo.end());
ベクターはテンプレートクラスであり、クラスの内容をポインターに変換することは安全ではありません。ベクタークラスを継承してこの新しい機能を追加することはできません。また、関数パラメーターを変更することは、実際には良いアイデアです。 Jstは、intベクトルtemp_foo(foo.begin [X]、foo.end())の別のベクトルを作成します。このベクトルを関数に渡します