g++ - 为什么这个没有语法错误的嵌套类程序会产生垃圾输出,我该如何解决?
问题描述
以下代码包含问题的完整描述作为 TODO。包括用于编译代码的剪切/粘贴命令行(无错误)。子实例包含它们自己的名称,初始化程序应该复制它。子实例还包含指向其父此实例的指针。这些都不应该打印垃圾。Child 还使用其 Parent 实例指针来打印父名称。此名称由 Parent ctor 初始化,因此不应打印为垃圾。我什至使用 -fsyntax-only 通过 clang 运行它,没有报告警告/错误。我肯定错过了什么。帮助将不胜感激。
////////////////////////////////////////////////////////////////////////////////
//
// ##### ## ##### ###### # # ##### #### ##### #####
// # # # # # # # ## # # # # # # # #
// # # # # # # ##### # # # # # # # # #
// ##### ###### ##### # # # # # ### # ##### #####
// # # # # # # # ## # ### # # # #
// # # # # # ###### # # # ### #### # #
////////////////////////////////////////////////////////////////////////////////
// A class having access to all nested class instances and vice versa
// 0. presence by name in a set
// 1. by name in a map
// 2. by index in a vector
// 3. by name to index in a map
// and nested classes have access to parent and to each other through parent.
////////////////////////////////////////////////////////////////////////////////
// TODO produce the following instead of garbage output.
// Compile and expected output:
// $ g++ --std=c++17 -Wall -pedantic -o parent parent.cpp
// $ ./parent
// P:A
// P:B
// $
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
using namespace std;
// Utility function for when things go wrong.
template<class... Args> void panic(Args... args) {
cerr << "parent panic: ";
(cerr << ... << args) << "\n";
exit(1);
}
class Parent { public: //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
class Child { public: //cccccccccccccccccccccccccccccccccccccccccccccccccccc
Child(Parent* p, const string& n) : parent(p), name(n) {} // Child ctor
~Child() {} // Child dtor
void operator()(){ cout<<parent->name<<':'<<name<<endl; } // Child ftor
Parent* parent; // Child Parent ptr
const string& name; // Child name
}; //ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
Parent(const string& name) : name(name) {} // Parent ctor
~Parent() {} // Parent dtor
void operator()() { for(auto child: vcci) { child(); } } // Parent ftor
void operator+=(const vector<string>& names) {
for(auto name : names) {
if (used.find(name) != used.end()) panic(name, " re-used,");
used.insert(name); // Fast search
size_t vcN = vcci.size(); // Index for next name
vcci.emplace_back(this, name); // construct child into vector
Child* back = &(vcci[vcN]); // Address of child to store
mptr[name] = back; // Store address of child
mint[name] = vcN; // map name to index
}
}
string name; // name of parent
set<string> used; // fast lookup of name for duplicates
vector<Child> vcci; // vector of emplaced Child instances
map<string, Child*> mptr; // name lookup of Child pointer
map<string, size_t> mint; // index of name
}; //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
//eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
void experiment() {
vector<string> AB = { "A", "B" }; // Names to use as Child names
Parent parent("P"); // Named parent
parent += AB; // Produce named Child instances
parent(); // Execute parent ftor
}
//mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
int main(int argc, char** argv) {
experiment();
return 0;
}
解决方案
With for(auto name : names) ...
,name
是一个局部变量,它是向量中字符串的副本。该变量在循环的每次迭代中创建和销毁。然后,您使用作为参数创建Child
实例- 它们将对该变量的引用存储在其成员中。不久之后,变量被销毁,所有这些引用都变得悬空。name
name
到程序实际尝试使用Child::name
成员时,字符串早已不复存在,引用也长期悬空。通过在对象的生命周期结束后访问对象,任何使用它们的尝试都会表现出未定义的行为。
推荐阅读
- sql - ORACLE ORA-00904: 无效标识符错误
- python - 使用 Python 单击“下载为 csv”按钮
- javascript - React - JSX 在条件渲染上没有改变
- java - Springboot缓存不适用于后续按需清除缓存调用
- java - 我怎样才能使它读取超过 255 个 Unicode 字符的 InputStream 子类读取这些字符并创建一个字节数组而不会溢出?
- c - C 中的 TCP 回显服务器/客户端,recv_all,send_all - 由我实现,recv 不起作用
- github - Github:页面构建超时
- php - 在sql中获取交叉引用并在php中显示
- c - 在 C 中处理 2 个静态二维数组的正确方法是什么?
- python-3.7 - 如何使用多重继承获取一些父类属性值