C++ C+中的构造函数初始值设定项列表+;
请先查看以下代码:C++ C+中的构造函数初始值设定项列表+;,c++,c++11,initializer,C++,C++11,Initializer,请先查看以下代码: class StrBlob { public: StrBlob(); // .... private: std::shared_ptr<std::vector<std::string> > data; } //initializer empty into data ; StrBlob::StrBlob() // : data(std::make_shared<std::vector
class StrBlob
{
public:
StrBlob();
// ....
private:
std::shared_ptr<std::vector<std::string> > data;
}
//initializer empty into data ;
StrBlob::StrBlob()
// : data(std::make_shared<std::vector<std::string> >()) // compile success
{
// data(std::make_shared<std::vector<std::string> >()); // compile error
}
int main()
{
// this statement can compile
std::shared_ptr<std::vector<std::string> >data(std::make_shared<std::vector<std::string> >());
return 0;
}
类StrBlob
{
公众:
StrBlob();
// ....
私人:
std::共享的ptr数据;
}
//初始化器清空数据;
StrBlob::StrBlob()
//:data(std::make_shared())//编译成功
{
//数据(std::make_shared());//编译错误
}
int main()
{
//此语句可以编译
std::shared_ptrdata(std::make_shared());
返回0;
}
我想知道为什么上面的语句编译出现错误
error: no match for call to ‘(std::shared_ptr<std::vector<std::__cxx11::basic_string<char> > >)
(std::shared_ptr<std::vector<std::__cxx11::basic_string<char> > >)’
data(std::make_shared<std::vector<std::string> >());
错误:调用(std::shared_ptr)不匹配
(标准::共享_ptr)'
数据(std::make_shared());
C++初级读物5(第7.5章)中引用的相应知识如下:
我们可以经常(但并非总是)忽略成员是初始化还是分配的区别。必须初始化常量或引用的成员。类似地,属于未定义默认构造函数的类类型的成员也必须初始化
首先,我将分享我的想法。在构造函数体开始执行之前,“data”成员是默认初始化的。正确的?因此,构造函数中的“data”成员将复制从函数make_shared创建的对象。对吗 第一个编译成功,因为您初始化了成员初始值设定项列表中的数据,并且这种语法在这里完全有效。查看更多信息 第二个等于数据(…)。它不是数据对象的构造,编译器将其视为对已创建的数据成员调用运算符()的尝试(并在错误消息中说明)
最后,在main函数中,您只需使用shared_ptr copy构造函数从make_shared返回的shared_ptr创建数据。第一个函数编译成功,因为您在成员初始值设定项列表中初始化了数据,并且这种语法在这里完全有效。查看更多信息 第二个等于数据(…)。它不是数据对象的构造,编译器将其视为对已创建的数据成员调用运算符()的尝试(并在错误消息中说明)
最后,在main函数中,您只需使用shared_ptr copy构造函数从make_shared返回的shared_ptr创建数据。如果出于多种原因以后要初始化数据对象,您可以在StrBlob初始化列表和StrBlob构造函数的主体中使用std::shared_ptr默认构造函数-重置函数:
StrBlob::StrBlob()
: data()
{
data.reset(new std::vector<std::string>());
}
StrBlob::StrBlob()
:data()
{
data.reset(新的std::vector());
}
如果出于多种原因希望稍后初始化数据对象,可以在StrBlob初始化列表和StrBlob构造函数主体中使用std::shared_ptr默认构造函数-重置函数:
StrBlob::StrBlob()
: data()
{
data.reset(new std::vector<std::string>());
}
StrBlob::StrBlob()
:data()
{
data.reset(新的std::vector());
}
因为您无法在构造函数体内部构造/初始化这样的对象。它只允许在初始值设定项列表中使用。你可以分配给已经在体内的已经构建的对象,但是“你可以分配给已经在体内的已经构建的对象”,但是你不应该在C++代码中养成习惯,因为你不能在构造函数的主体中构建/初始化像这样的对象。它只允许在初始值设定项列表中使用。你可以分配给已经在体内的已经构建的对象。“你可以指派已经在体内的已经构建的对象”,但是你不应该在C++代码中养成习惯。我认为我们应该避免这样的结构,因为这个代码不是最佳的。例如,参见迈尔斯的书。@Edgarokyan这是一个简单的例子。实际上,不能总是在初始化列表中初始化对象,因为有时需要计算一些输入参数。关于效率,我只调用默认构造函数和重置函数。我创建了一次向量对象。我不怀疑你的答案。事实上,我同意这一点。我的帖子的目的是展示另一种解决方案。我认为我们应该避免这种构造,因为这种代码不是最优的。例如,参见迈尔斯的书。@Edgarokyan这是一个简单的例子。实际上,不能总是在初始化列表中初始化对象,因为有时需要计算一些输入参数。关于效率,我只调用默认构造函数和重置函数。我创建了一次向量对象。我不怀疑你的答案。事实上,我同意这一点。我的帖子的目的是展示另一个解决方案。你说得对。第二个数据(..)是调用复制构造函数?但是数据对象已经在调用数据(..)之前创建。如果是的话。这意味着调用复制构造函数两次。编译时会出现错误。我说的对吗?不,第二个不是复制构造函数调用。它是对操作符()
的调用,对于您的类来说,它没有重载。这就是它无法编译的原因。在你不同意我的想法之前,我想了一会儿。我试图重载操作符()成员。而且它起作用了。对应编译器给出的错误,我想我知道。祝你万事如意!最后,我想问一下,它是否也可能是错误的,因为调用了两次复制构造函数,只是编译器没有报告错误???@AndyCong我不明白如何调用一个复制构造函数两次。在成员初始值设定项列表中只有一个调用…也许这些是我的观点错误。我想得太多了。因为数据的行为(..)看起来像复制构造函数,我认为问题可以简化如下代码:std::vector vec1,vec2;vec1(vec2);然后第二种说法就是我们讨论的问题。这似乎是复制构造函数的行为吗?你认为呢?我需要你的帮助,你说得对。第二个数据(..)是调用复制构造函数?但是数据对象是