私がこれを行うとき:
std::vector<int> hello;
すべてがうまく機能します。ただし、代わりに参照のベクトルにする場合:
std::vector<int &> hello;
次のような恐ろしいエラーが発生します
エラーC2528: 'pointer':参照へのポインターが無効です
構造体への参照の束をベクトルに入れたいので、ポインターをいじる必要はありません。ベクトルがこれについてかんしゃくを投げるのはなぜですか?代わりにポインターのベクトルを使用する唯一のオプションはありますか?
ベクトルなどのコンテナのコンポーネントタイプは assignable でなければなりません。参照は割り当てられません(宣言されたときに初期化できるのは一度だけで、後で他の何かを参照させることはできません)。他の割り当て不可能なタイプも、コンテナのコンポーネントとして許可されていません。 vector<const int>
は許可されていません。
はい、できます std::reference_wrapper
を探します
本質的に、参照は作成時にのみ設定できます。つまり、次の2行の効果は大きく異なります。
int & A = B; // makes A an alias for B
A = C; // assigns value of C to B.
さらに、これは違法です:
int & D; // must be set to a int variable.
ただし、ベクトルを作成する場合、作成時にそのアイテムに値を割り当てる方法はありません。あなたは本質的に最後の例の束を作っているだけです。
イオン・トディレルはすでに答えを述べていましたYESstd::reference_wrapper
を使用しています。 C++ 11からstd::vector
からオブジェクトを取得し、std::remove_reference
を使用して参照を削除するメカニズムがあります。以下に、g++
およびclang
をオプション付きで使用してコンパイルした例を示します-std=c++11
および正常に実行されました。
#include <iostream>
#include <vector>
#include<functional>
class MyClass {
public:
void func() {
std::cout << "I am func \n";
}
MyClass(int y) : x(y) {}
int getval()
{
return x;
}
private:
int x;
};
int main() {
std::vector<std::reference_wrapper<MyClass>> vec;
MyClass obj1(2);
MyClass obj2(3);
MyClass& obj_ref1 = std::ref(obj1);
MyClass& obj_ref2 = obj2;
vec.Push_back(obj_ref1);
vec.Push_back(obj_ref2);
for (auto obj3 : vec)
{
std::remove_reference<MyClass&>::type(obj3).func();
std::cout << std::remove_reference<MyClass&>::type(obj3).getval() << "\n";
}
}
boost::ptr_vector<int>
は機能します。
Edit:はstd::vector< boost::ref<int> >
を使用することを提案しました。これはboost::ref
をデフォルトで構築できないため機能しません。
これは、C++言語の欠陥です。参照しようとすると、オブジェクトのアドレスが参照されるため、参照のアドレスを取得できません。したがって、参照へのポインタを取得することはできません。 std::vector
は、その要素へのポインターで動作するため、格納されている値を指すことができる必要があります。代わりにポインターを使用する必要があります。
他の人が言及したように、おそらくポインターのベクトルを代わりに使用することになります。
ただし、代わりに ptr_vector を使用することを検討してください。
std::reference_wrapper
を次のように使用します。
#include <functional>
#include <string>
#include <vector>
#include <iostream>
int main()
{
std::string hello = "Hello, ";
std::string world = "everyone!";
typedef std::vector<std::reference_wrapper<std::string>> vec_t;
vec_t vec = {hello, world};
vec[1].get() = "world!";
std::cout << hello << world << std::endl;
return 0;
}
標準の提案 のように、タイプX
のオブジェクトを含む標準コンテナT
の場合、T
はErasable
のX
でなければなりません。
Erasable
は、次の式の形式が正しいことを意味します。
allocator_traits<A>::destroy(m, p)
A
はコンテナのアロケータタイプ、m
はアロケータインスタンス、p
はタイプ*T
のポインタです。 Erasable
の定義については、 here を参照してください。
デフォルトでは、std::allocator<T>
がベクターのアロケーターとして使用されます。デフォルトのアロケーターでは、要件はp->~T()
の有効性と同等です(T
は参照型であり、p
は参照へのポインターです)。ただし、- 参照へのポインターは無効です であるため、式の形式が適切ではありません。
他のコメントが示唆しているように、あなたはポインタの使用に限定されています。しかし、それが役立つ場合、ポインターに直接直面することを避けるための1つのテクニックがあります。
次のようなことができます。
vector<int*> iarray;
int default_item = 0; // for handling out-of-range exception
int& get_item_as_ref(unsigned int idx) {
// handling out-of-range exception
if(idx >= iarray.size())
return default_item;
return reinterpret_cast<int&>(*iarray[idx]);
}