Mon*_*urd 8 c++ constructor stl copy-constructor temporary-objects
我创建了一个简单的测试用例,展示了我在一个更大的代码库中注意到的奇怪行为.这个测试用例如下.我依靠STL Map的"[]"运算符来创建指向这种结构的映射中的结构的指针.在下面的测试用例中,线...
TestStruct *thisTestStruct = &testStructMap["test"];
Run Code Online (Sandbox Code Playgroud)
...给我指针(并在地图中创建一个新条目).我注意到的奇怪之处在于,这一行不仅会导致地图中的新条目被创建(因为"[]"运算符),但由于某种原因,它会导致结构体的析构函数被多次调用两次.我显然错过了一些东西 - 非常感谢任何帮助!谢谢!
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct TestStruct;
int main (int argc, char * const argv[]) {
map<string, TestStruct> testStructMap;
std::cout << "Marker One\n";
//why does this line cause "~TestStruct()" to be invoked twice?
TestStruct *thisTestStruct = &testStructMap["test"];
std::cout << "Marker Two\n";
return 0;
}
struct TestStruct{
TestStruct(){
std::cout << "TestStruct Constructor!\n";
}
~TestStruct(){
std::cout << "TestStruct Destructor!\n";
}
};
Run Code Online (Sandbox Code Playgroud)
上面的代码输出以下内容......
/*
Marker One
TestStruct Constructor! //makes sense
TestStruct Destructor! //<---why?
TestStruct Destructor! //<---god why?
Marker Two
TestStruct Destructor! //makes sense
*/
Run Code Online (Sandbox Code Playgroud)
...但我不明白是什么原因导致TestStruct的析构函数的前两次调用?(我认为最后一个析构函数调用是有意义的,因为testStructMap超出了范围.)
AnT*_*AnT 18
功能std::map<>::operator[]相当于
(*((std::map<>::insert(std::make_pair(x, T()))).first)).second
Run Code Online (Sandbox Code Playgroud)
表达式,如语言规范中所指定.正如您所看到的,这涉及默认构造类型的临时对象T,将其复制到std::pair对象中,稍后将其复制(再次)到地图的新元素中(假设它已经不存在).显然,这会产生一些中间T对象.您在实验中观察到的破坏这些中间物体.您错过了他们的构造,因为您没有从班级的复制构造函数生成任何反馈.
中间对象的确切数量可能取决于编译器优化功能,因此结果可能会有所不同.
你有一些看不见的副本:
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct TestStruct;
int main (int argc, char * const argv[]) {
map<string, TestStruct> testStructMap;
std::cout << "Marker One\n";
//why does this line cause "~TestStruct()" to be invoked twice?
TestStruct *thisTestStruct = &testStructMap["test"];
std::cout << "Marker Two\n";
return 0;
}
struct TestStruct{
TestStruct(){
std::cout << "TestStruct Constructor!\n";
}
TestStruct( TestStruct const& other) {
std::cout << "TestStruct copy Constructor!\n";
}
TestStruct& operator=( TestStruct const& rhs) {
std::cout << "TestStruct copy assignment!\n";
}
~TestStruct(){
std::cout << "TestStruct Destructor!\n";
}
};
Run Code Online (Sandbox Code Playgroud)
结果是:
Marker One
TestStruct Constructor!
TestStruct copy Constructor!
TestStruct copy Constructor!
TestStruct Destructor!
TestStruct Destructor!
Marker Two
TestStruct Destructor!
Run Code Online (Sandbox Code Playgroud)
将以下内容添加到TestStruct的界面:
TestStruct(const TestStruct& other) {
std::cout << "TestStruct Copy Constructor!\n";
}
Run Code Online (Sandbox Code Playgroud)