C++ 向量 push_back
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7382090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ vector push_back
提问by user623879
What is the proper way of pushing a new object element onto a std::vector
? I want the data to be allocated in the vector. Will this copy the object newradio
into the vector and then get rid of newradio
when it goes out of scope (e.g. out of the stack)?
将新对象元素推送到 的正确方法是std::vector
什么?我希望在向量中分配数据。这是否会将对象复制newradio
到向量中,然后newradio
在它超出范围(例如,超出堆栈)时将其删除?
vector<Radio> m_radios;
Radio newradio(radioNum);
m_radios.push_back(newradio);
And then when I free the object containing m_radios
, will this free all the memory allocated by the vector?
然后当我释放包含 的对象时m_radios
,这会释放向量分配的所有内存吗?
回答by Etienne de Martel
std::vector
manages its own memory. That means that, when the destructor of a vector is invoked the memory held by the vector is released. std::vector
also invokes an object's destructor when it is removed (through erase
, pop_back
, clear
or the vector's destructor).
std::vector
管理自己的内存。这意味着,当调用向量的析构函数时,向量所持有的内存被释放。std::vector
还调用时,它被移除对象的析构函数(通过erase
,pop_back
,clear
或载体的析构函数)。
When you do this:
当你这样做时:
Radio newradio(radioNum);
m_radios.push_back(newradio);
You add a copy of newradio
(created using Radio
's copy constructor) to the vector. newradio
will be destroyed when it goes out of scope, and the copy will be destroyed when it is removed from the vector (as for any object).
您将newradio
(使用Radio
的复制构造函数创建)的副本添加到向量中。newradio
当它超出范围时将被销毁,当它从向量中移除时(对于任何对象),副本将被销毁。
That's an important point: std::vector
only stores copiesof an object, which means the object must have a meaningful copy constructor (and an assignment operator, but that's another issue). If you have a vector of pointers, then the pointer itself will be copied, and not what it points to. Note that this behavior is the same for every standard container (like std::list
or std::set
).
这是很重要的一点:std::vector
只存储对象的副本,这意味着该对象必须有一个有意义的复制构造函数(和一个赋值运算符,但这是另一个问题)。如果您有一个指针向量,则将复制指针本身,而不是它指向的内容。请注意,此行为对于每个标准容器(如std::list
或std::set
)都是相同的。
As a rule of thumb, if you're not using pointers, then you don't have to worry about releasing the memory yourself.
根据经验,如果您不使用指针,则不必担心自己释放内存。
In C++11, most standard containers (including vector
) have an emplace_back
method that constructs an object in placeat the end of the container. It takes a bunch of parameters and calls the constructor that best matches those parameters (or fails if no such constructor exist), using said constructor to create the object, without any copy, at the end of the container. So, the above code could be rewritten as:
在 C++11 中,大多数标准容器(包括vector
)都有一个emplace_back
方法,可以在容器的末尾构造一个对象。它需要一堆参数并调用与这些参数最匹配的构造函数(如果不存在这样的构造函数则失败),使用所述构造函数在容器的末尾创建对象,没有任何副本。所以,上面的代码可以改写为:
m_radios.emplace_back(radioNum); // construct a Radio in place,
// passing radioNum as the constructor argument
Also in C++11, containers are usually move aware, so they no longer require objects to be copiable: if they are movable, then the container will move its contents as required (such as during reallocations, for instance). Copiable types are still required if you want to copy the vector.
同样在 C++11 中,容器通常是移动感知的,因此它们不再需要对象是可复制的:如果它们是可移动的,那么容器将根据需要移动其内容(例如在重新分配期间)。如果要复制向量,仍然需要可复制类型。
回答by K-ballo
push_back()
will store a copy of its argument within the vector. As long as Radio
implements proper value semantics, there will be no problems with it.
push_back()
将其参数的副本存储在向量中。只要Radio
实现了正确的值语义,就不会有问题。
回答by Monotosh Mondal
Try this:
尝试这个:
#include<iostream.h>
#include<vector.h>
class base
{
int i;
public:
base(int z=0){i=z;cout<<"okk constructor "<<i<<" called\n";}
base(const base& b1){i=b1.i;cout<<"copy constructor "<<i<<" called\n";}
void display(){cout<<" val is "<<i<<" \n";}
~base(){cout<<"destructor of "<<i<<" base called\n";}
};
int main()
{
cout<<"before anything\n";
vector<base> basev;
base baseobj1(1);
base baseobj2(2);
base baseobj3(3);
base baseobj4(4);
base baseobj5(5);
base baseobj6(6);
base baseobj7(7);
base baseobj8(8);
base baseobj9(9);
base baseobj10(10);
basev.push_back(baseobj1);
cout<<"second push back\n";
basev.push_back(baseobj2);
cout<<"third push back\n";
basev.push_back(baseobj3);
cout<<"fourth push back\n";
basev.push_back(baseobj4);
cout<<"fifth push back\n";
basev.push_back(baseobj5);
cout<<"sixth push back\n";
basev.push_back(baseobj6);
cout<<"seventh push back\n";
basev.push_back(baseobj7);
cout<<"eighth push back\n";
basev.push_back(baseobj8);
cout<<"ninth push back\n";
basev.push_back(baseobj9);
cout<<"10th push back\n";
basev.push_back(baseobj10);
cout<<"after all push back\n";
cout<<"before clear\n";
basev.clear();
cout<<"after clear\n";
}
output:
输出:
before anything
okk constructor 1 called
okk constructor 2 called
okk constructor 3 called
okk constructor 4 called
okk constructor 5 called
okk constructor 6 called
okk constructor 7 called
okk constructor 8 called
okk constructor 9 called
okk constructor 10 called
copy constructor 1 called
second push back
copy constructor 1 called
copy constructor 2 called
destructor of 1 base called
third push back
copy constructor 1 called
copy constructor 2 called
copy constructor 3 called
destructor of 1 base called
destructor of 2 base called
fourth push back
copy constructor 4 called
fifth push back
copy constructor 1 called
copy constructor 2 called
copy constructor 3 called
copy constructor 4 called
copy constructor 5 called
destructor of 1 base called
destructor of 2 base called
destructor of 3 base called
destructor of 4 base called
sixth push back
copy constructor 6 called
seventh push back
copy constructor 7 called
eighth push back
copy constructor 8 called
ninth push back
copy constructor 1 called
copy constructor 2 called
copy constructor 3 called
copy constructor 4 called
copy constructor 5 called
copy constructor 6 called
copy constructor 7 called
copy constructor 8 called
copy constructor 9 called
destructor of 1 base called
destructor of 2 base called
destructor of 3 base called
destructor of 4 base called
destructor of 5 base called
destructor of 6 base called
destructor of 7 base called
destructor of 8 base called
10th push back
copy constructor 10 called
after all push back
before clear
destructor of 1 base called
destructor of 2 base called
destructor of 3 base called
destructor of 4 base called
destructor of 5 base called
destructor of 6 base called
destructor of 7 base called
destructor of 8 base called
destructor of 9 base called
destructor of 10 base called
after clear
destructor of 10 base called
destructor of 9 base called
destructor of 8 base called
destructor of 7 base called
destructor of 6 base called
destructor of 5 base called
destructor of 4 base called
destructor of 3 base called
destructor of 2 base called
destructor of 1 base called
回答by Jesus Ramos
Yes pushing newRadio will push a copy of the Radio object into the vector. You also don't need to free the vector because it is local only so it will be destroyed once you are out of its scope. If for instance you wrote
是的,推送 newRadio 会将 Radio 对象的副本推送到向量中。您也不需要释放向量,因为它仅是本地的,因此一旦超出其范围,它将被销毁。例如,如果你写
vector<Radio> *m_radios = new vector<Radio>();
Then you would have to free that memory by calling the vector destructor manually.
然后您必须通过手动调用向量析构函数来释放该内存。
回答by Mateen Ulhaq
Yup, radioNum
will be copiedinto m_radios
. As long as you're not deallocating pointers when newradio.~Radio();
occurs (out of scope), it's OK. If m_radios
, or a subclass uses pointers, you'll need to make the switch to smart pointers(shared_ptr
).
是的,radioNum
将被复制到m_radios
. 只要您在newradio.~Radio();
发生时不释放指针(超出范围),就可以了。如果m_radios
或子类使用指针,则需要切换到智能指针( shared_ptr
)。
When m_radios
goes out of scope, the destructor is automatically called, and all the stuff std::vector
holds is freed.
当m_radios
超出范围时,析构函数被自动调用,并且所有的东西std::vector
都被释放。
回答by Darren Engwirda
In addition to the other answers that verify that the object is copied into the container when using push_back
via calls to the copy constructor, you might also keep in mind the new emplace_back
functionality added with c++0x
.
除了在使用push_back
via 调用复制构造函数时验证对象是否复制到容器中的其他答案之外,您可能还会记住emplace_back
使用c++0x
.
Calling emplace_back
allows you to bypass the creation of any temporary objects and have the object constructed in-place inside the container directly. emplace_back
is a varardic template function that accepts the parameters you would pass to the constructor of your object, so in this case:
调用emplace_back
允许您绕过任何临时对象的创建,并直接在容器内就地构造对象。emplace_back
是一个可变模板函数,它接受您将传递给对象构造函数的参数,因此在这种情况下:
std::vector<Radio> m_radios;
m_radios.emplace_back(radioNum);
will not create any intermediate temporaries. This can be helpful if your objects are expensive to copy.
不会创建任何中间临时文件。如果您的对象复制成本很高,这会很有帮助。
Hope this helps.
希望这可以帮助。
回答by nuKs
By default, std::vector manages the memory itself using the copy constructor of the underlying class. So, it acts a bit as if the vector element was a local variable (when the vector goes out of scope, the element gets destructed).
默认情况下, std::vector 使用底层类的复制构造函数管理内存本身。所以,它有点像向量元素是一个局部变量(当向量超出范围时,元素被破坏)。
When you don't want this behavior, you can use a vector of pointer or boost::ptr_vector instead.
当您不想要这种行为时,您可以使用指针向量或 boost::ptr_vector 代替。