我有一些这样的代码:
struct Data {
Data(const std::vector<int> &data = {}) : data_(data) {}
const std::vector<int> &data_;
};
Data create1() {
return Data(); // bad
}
Data create2() {
return Data({}); // bad
}
Data create3(const std::vector<int> &data = {}) {
return Data(data); // good
}
Data create4() {
static const std::vector<int> data;
return Data(data); // good
}
void main() {
auto data1 = create1(); // deleted data_
auto data2 = create2(); // deleted data_
auto data3 = create3(); // ok
auto data4 = create4(); // ok
}
这四个创建函数对我来说似乎是相同的。但是为什么create1和create2导致删除的data_但create3和create4没问题?
答案 0 :(得分:1)
创建静态数据成员并将其用于初始化:
struct Data {
Data(const std::vector<int> &data = empty_) : data_(data) {}
const std::vector<int> &data_;
private:
static std::vector<int> empty_;
};
std::vector<int> Data::empty_ = {};
Data create1() {
return Data(); // good
}
Data create2() {
return Data({}); // still bad, as it should be
}
Data create3(const std::vector<int> &data = {}) {
return Data(data); // good
}
Data create4() {
static const std::vector<int> data;
return Data(data); // good
}
void main() {
auto data1 = create1(); // ok
auto data2 = create2(); // deleted data_
auto data3 = create3(); // ok
auto data4 = create4(); // ok
}
答案 1 :(得分:1)
前两个案例非常明显地滥用了临时人员。根据提问者的评论,他们已经了解到create1
和create2
出了什么问题,所以让我们集中讨论create3
及其起作用的原因。
剧透:没有。
我将对代码进行一些自由处理,以使发生的事情更加明显。首先,我们用一个简单的类替换vector
,让我们更好地了解构造和破坏。
struct test
{
test()
{
std::cout << "test ctor\n";
}
~test()
{
std::cout << "test dtor\n";
}
};
现在,我们执行类似于Data
的操作,并使其使用test
代替vector
struct Data {
Data(const test &data = {}) : data_(data)
{
std::cout << "data ctor\n";
}
~Data()
{
std::cout << "data dtor\n";
}
const test &data_;
void forceuse() // just to make sure the compiler doesn't get any bright ideas about
// optimizing Data out before we're through with it.
{
std::cout << "Using data\n";
}
};
我们为create3
添加了一些额外的诊断,并再次将vector
替换为test
Data create3(const test &data = {}) {
std::cout << "in create3\n";
return Data(data); // good
}
并对main
int main() {
{ // change the scope of data3 so that we can put a breakpoint at the end of main
// and watch all of the fun
std::cout << "calling create3\n";
auto data3 = create3(); // ok
std::cout << "returned from create3\n";
data3.forceuse();
}
}
此输出为
calling create3
test ctor
in create3
data ctor
test dtor
returned from create3
Using data
data dtor
test
是在调用create3
期间创建的,并在从create3
退出时销毁。它在main
中还没有生命。如果它在main
中似乎还活着,那真是愚蠢的运气。您的朋友和我的未定义行为是个混蛋。再次。
test
在Data
之前创建,但在Data
之前销毁,从而使Data
处于不良状态。
上面的代码都很好地组装并在在线IDE中运行:https://ideone.com/XY30XH