我是 C++ 新手,所以有一个问题。
有C++代码:
class Test
{
public:
std::string name;
Test(){};
Test(std::string name) {
std::cout << "Create " << name << '\n';
Test::name = name;
};
~Test() {std::cout << "Destroy " << name << '\n';}
};
std::vector<Test> test {Test("one"), Test("two"), Test("three")};
void main()
{
for (auto i : test)
std::cout << i.name << '\n';
std::cout << "Clear\n";
test.clear();
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
Create one
Create two
Create three
Destroy three
Destroy two
Destroy one
one
Destroy one
two
Destroy two
three
Destroy three
Clear
Destroy one
Destroy two
Destroy three
Run Code Online (Sandbox Code Playgroud)
为什么编译器会多次销毁向量中的对象,而何时必须销毁一次?该代码有什么问题吗?
使用默认选项编译 Microsoft cl.exe x64。
让我们添加一个复制构造函数(并使用较小的测试用例,以减少冗长),看看会发生什么......
#include <iostream>
#include <string>
#include <vector>
class Test
{
public:
std::string name;
Test(){};
Test(std::string name) : name(name) {
std::cout << "New " << name << '\n';
}
Test(const Test& other) : name("Copy of " + other.name) {
std::cout << "Copied " << other.name << '\n';
}
~Test() {std::cout << "Destroy " << name << '\n';}
};
std::vector<Test> test {Test("Original") };
int main()
{
std::cout << "Loop:\n";
for (auto i : test)
std::cout << "This is " << i.name << '\n';
std::cout << "Clear\n";
test.clear();
}
Run Code Online (Sandbox Code Playgroud)
这会产生
New Original
Copied Original
Destroy Original
Loop:
Copied Copy of Original
This is Copy of Copy of Original
Destroy Copy of Copy of Original
Clear
Destroy Copy of Original
Run Code Online (Sandbox Code Playgroud)
解释:
New Original -- The object in the initialzer list
Copied Original -- Here it gets copied into the vector
Destroy Original -- The original is destroyed along with the initializer list
Loop:
Copied Copy of Original -- Copied into the loop variable
This is Copy of Copy of Original -- Printing in the loop
Destroy Copy of Copy of Original -- The temporary loop object is destroyed
Clear
Destroy Copy of Original -- Clearing the vector
Run Code Online (Sandbox Code Playgroud)
如果您循环引用,i将引用向量内的对象而不是它的副本 - 只需将一行更改为
for (auto& i : test)
Run Code Online (Sandbox Code Playgroud)
将输出更改为
New Original
Copied Original
Destroy Original
Loop:
This is Copy of Original
Clear
Destroy Copy of Original
Run Code Online (Sandbox Code Playgroud)
您可以通过直接在向量内创建对象来摆脱进一步的复制:
int main()
{
std::vector<Test> test;
test.emplace_back("Original");
std::cout << "Loop:\n";
for (auto& i : test)
std::cout << "This is " << i.name << '\n';
std::cout << "Clear\n";
test.clear();
}
Run Code Online (Sandbox Code Playgroud)
输出:
Original
Loop:
This is Original
Clear
Destroy Original
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
102 次 |
| 最近记录: |