C++ 创建类对象的向量时,何时调用构造函数?
假设我有一门课叫Foo。Foo没有默认的构造函数。它有一个构造函数Foo(intx,float y) Bar是一个容器类。它包含一个包含Foo实例的向量C++ 创建类对象的向量时,何时调用构造函数?,c++,class,vector,C++,Class,Vector,假设我有一门课叫Foo。Foo没有默认的构造函数。它有一个构造函数Foo(intx,float y) Bar是一个容器类。它包含一个包含Foo实例的向量 Bar::Bar(int numberOfFoos, int x, float y) { foovector.resize (numberOfFoos); for(int i = 0; i < numberOfFoos; i++) { **read below** } 但是我不能以这种方式使用点访问操作符调用构造函数。此时我甚至
Bar::Bar(int numberOfFoos, int x, float y) {
foovector.resize (numberOfFoos);
for(int i = 0; i < numberOfFoos; i++) {
**read below**
}
但是我不能以这种方式使用点访问操作符调用构造函数。此时我甚至不知道resize函数是否已经调用了构造函数
问题是,我该怎么做
关于类向量的另一个相关问题:
在Foo中,有一个向量包含浮点数。float x参数是它应该保持的浮点数。Foo的构造函数有一行
arrayofFloats.resize (x);
但这意味着计算机事先不知道Foo的大小。每个foo可以有不同的大小。这不会给Foo的向量带来问题吗?如果每个Foo可以有不同的大小,那么如何声明特定大小的向量
对不起,英语不好,我希望它已经足够清楚了
谢谢。不要使用
调整大小
来保留空间。相反,请使用保留
:
foovector.reserve(n); // reserves memory only, no object
// constructions take place
for (std::size_t i = 0; i != n; ++i)
{
foovector.emplace_back(12 * i, i / 3.0); // pushes a new Foo(12*i, i/3.0)
} // at the back of the vector
resize
初始化新元素;具体来说,它使用value初始化一个临时对象(如果它是类类型,则使用默认构造函数),然后使用copy初始化每个元素
如果它没有默认构造函数,或者无法进行复制初始化,则不能使用
调整大小
但是,您可以使用reserve
来保留内存,而无需初始化内存中的任何对象;然后使用push_back
或insert
元素插入该空间。在C++11中,还可以使用emplace\u back
来避免复制元素:
foovector.reserve (numberOfFoos);
for(int i = 0; i < numberOfFoos; i++) {
foovector.push_back(Foo(42, 1.23)); // C++03, requires copy constructor
foovector.emplace_back(42, 1.23); // C++11, doesn't require copy constructor
}
foovector.reserve(numberofoos);
for(int i=0;i
关于你的额外问题:
但这意味着计算机事先不知道Foo的大小
是的。向量是一个小对象,包含指向某个动态分配内存的指针;它的大小是固定的,并不取决于它分配了多少内存。如果我理解正确,您希望Bar构造函数在一个向量中构造多个Foo实例,每次都使用Foo构造函数的相同参数如果Foo构造函数的工作方式使Foo对象在构造后都是相同的,则可以使用
std::vector::assign(size\u type n,const value\u type&val)
,在这种情况下,value\u type是Foo。如果调用foovector.assign(numberofoos,Foo(x,y))
,向量将构造一个临时Foo对象,并用该对象的numberofoos
副本填充自身assign()
还可以处理您的所有大小调整需求
但是,如果Foo构造函数涉及随机行为、静态计数器或其他导致对构造函数的连续调用产生不同对象的内容,那么复制就不是您想要的
你的另一个问题:
在C++中,每种类型都有固定的大小。(这就是多态性仅适用于指针或按引用传递语义的原因。)许多类,如std::vector
,管理可以根据需要增加或减少的额外内存。这一切都是在幕后用指针完成的。附加内存(例如向量包含的数据)在其他一些内存位置处于关闭状态,不会影响实际内存
对象的大小。
vector
方法size()
、resize()
、和reserve()
都使用该托管内存。因此,无论向量中有多少项,Foo对象的大小都是相同的。可能重复“如果它没有默认构造函数,或者无法复制初始化,那么就不能使用resize”:我相信在C++11中,它将分别初始化每个元素,而不是复制(在这种情况下,void resize(size_type n);
有一个单独的重载)实际上,如果使用标准分配器,T
仍然需要CopyConstructible
,以便在resize
需要重新分配时将现有元素复制到新存储中,因此“如果它没有默认构造函数,或者不能进行复制初始化,那么就不能使用resize”在大多数情况下是正确的(如果您使用stanard分配器),但是“它值初始化一个临时对象(如果它是类类型,则使用默认构造函数),然后使用该值复制初始化每个元素。“绝对不是:新元素是单独初始化的值。现有元素被移动到新位置,而不是复制,因此它需要是可移动的。对于example@JonathanWakely我想我正在读一本旧的草稿(n3242),我的说“要求:T
应可复制插入*此
”……是否在最终版本中更新?我在某个地方读到,在重新分配期间移动存在异常安全问题。@JonathanWakely我正在读
(预处理后)它使用std::\uuuuuuu未初始化\uu move\uu if\uNoExcept\uA
,所以它大概只调用noexcept
移动构造函数,否则使用复制构造函数?
foovector.reserve (numberOfFoos);
for(int i = 0; i < numberOfFoos; i++) {
foovector.push_back(Foo(42, 1.23)); // C++03, requires copy constructor
foovector.emplace_back(42, 1.23); // C++11, doesn't require copy constructor
}