あなたの言葉の理解はややずれています。注釈付きのコードは次のとおりです。
vector<SomeClass> objs;
SomeClass obj; // create a new obj with a new name
objs.push_back(obj);
while (someConditionIsTrue()){
use(&obj);
obj = new SomeClass(); // create a new obj with an existing name
objs.pushback(obj)
}
これが実際に起こることです
// create an object called "objs" which is a std::vector header, on the stack.
vector<SomeClass> objs;
// create an instace of "SomeClass" on the stack, call it obj.
SomeClass obj;
// allocate storage in the heap for some number of SomeClass instances to
// act as the storage for "objs", and assign them to it's "m_data" member.
// default construct the first one,
// then call it's copy constructor with the stack instance of "Obj" to
// copy the values/data into the first entry of the heap allocation of objs.
objs.push_back(obj);
while (someConditionIsTrue()){
// pass a pointer to the stack-allocated instance of obj.
use(&obj);
// create a new instance of "SomeClass" on the heap,
// default/zero construct it,
// return the pointer to this heap allocation and pass it
// to obj.operator=(const SomeClass*) to copy the data into
// the stack space allocated for "obj".
obj = new SomeClass(); // create a new obj with an existing name
// leak the pointer to the previous heap allocation by not storing it.
// increase the size of the heap allocation backing objs and then
// default construct the first SomeClass instance in the new space,
// then copy our freshly copy-initialized stack instance back into it.
objs.pushback(obj)
}
このコードは他にもさまざまな方法で記述できますが、最も賢明な方法のようです。
std::vector<SomeClass> objs;
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1); // grow me a new element.
use(&objs.back());
}
または、「使用」を参照してください。
void use(SomeClass& obj);
//...
use(objs.back());
ローカルオブジェクトにエントリを試してもらいたい場合。
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1);
// the compiler will either optimize this out entirely,
// or use a pointer under the hood.
SomeClass& obj = objs.back();
use(&obj); // take the address of the object obj references.
}
また、「resize()」はコストが高くなる可能性があることに注意してください。これを前もって行うことをお勧めします。
objs.reserve(1024); // or something you know is likely to cover most use cases.
あなたが本当に、本当にポインタを使わなければならないなら。
SomeClass* obj = nullptr;
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1);
obj = &objs.back();
use(obj);
}
"objs.resize()" の代わりに、placement-new を ctor で使用できる場合があります。
objs.emplace_back(SomeClass());
他の人はあなたが使用することを提案しています
obj = Someclass();
ただし、これはオブジェクトのデフォルトで構築されたスタック コピーをコピーしていることに注意してください。
{
SomeClass tempObj;
obj.operator=(std::move(tempObj));
}
それはあなたが本当にやりたいことだとは思いません。次のようなスタック ローカル コピーを作成するよりもコストがかかります。
while (someCondition()) {
SomeClass stackCopy;
...
}
コンパイラは、ループごとにスタック領域を放棄しないほど十分にスマートです。それが行うことは、同じオブジェクトでコンストラクターを再度呼び出すための「Placement new」と呼ばれるものです。
SomeClass obj;
while (someCondition()) {
new (&obj) SomeClass(); // Call SomeClass() ctor on the memory at &obj
...
}
しかし - これは基本的に、コンパイラが以前のコード サンプルをどのように達成したかです。