std::cout 打印变量与函数表达式时的行为不同
std::cout behaves differently when printing variable vs function expression
我是 c++ 的新手,我正面临 std::cout
的一种我不理解的奇怪行为。特别是,当我想使用 cout << nd.next[2]->next[17]->val
打印第二个节点的值时,我得到了一些复杂的字节。但是,如果我先将它设置为一个变量,例如 string let2 = nd.next[2]->next[17]->val
,然后使用 cout << let2
,它会打印出正确的字符。我的代码在下面,我正在实施一个特里。 (此外,由于我对 C++ 还很陌生,因此我感谢您对我在代码中做错的任何其他评论)
#include <iostream>
#include <set>
#include <iterator>
#include <map>
#include <string>
#include <unordered_map>
using std::set;
using std::cout;
using std::endl;
using std::string;
struct Node {
Node* next[26];
string val;
void insert(string str) {
cout << "insert " << str << endl;
insert(str, 0);
}
void insert(string str, int idx) {
if (idx >= str.length()) {
return;
}
char cur = str[idx];
int curIdx = cur - 'a';
cout << "cur: " << cur << endl;
cout << "cur idx: " << curIdx << endl;
if (!next[curIdx]) {
Node newNode = Node();
newNode.val = cur;
next[curIdx] = &newNode;
}
next[curIdx]->insert(str, idx+1);
}
};
int plus(int a, int b) {
return a+b;
}
int main() {
Node nd = Node();
nd.insert("cryptography");
string let1 = nd.next[2]->val;
string let2 = nd.next[2]->next[17]->val;
cout << "first letter " << let1 << endl; // c
cout << "second letter " << nd.next[2]->next[17]->val << endl; // wrong
cout << "second letter " << let2 << endl; // work as expected
cout << "sum " << plus(1,2) << endl; // work as expected
// cout << nd.next[2]->next[17]->val << endl;
return 0;
}
关于问题的第二部分 ("what I am doing wrong"),在 insert()
方法中,您在堆栈上创建 Node()
对象并使用指向此对象的指针分配 next[curIdx]
目的。但是一旦执行超出定义该对象的范围,该堆栈对象就会自动销毁,因此 next[curIdx]
最终指向垃圾(对象在销毁之前曾经所在的内存)。
不确定下一行是如何工作的,next[curIdx]
此时指向垃圾:next[curIdx]->insert(str, idx+1);
相反,您应该使用 new
运算符在堆上分配 Node 对象,例如:
if (!next[curIdx]) {
next[curIdx] = new Node(); // allocated on heap
next[curIdx]->val = cur;
}
但是你应该确保在某个时候释放(delete
)它们以避免内存泄漏。 Node 的析构函数可能是一个很好的地方——你可以递归地 delete
来自下一个数组的所有非空节点。
您也可以使用 smart pointers 而不是原始指针,它们会在无法再访问对象时自动删除对象(垃圾收集器会在 Java 和 C# 等其他语言中自动执行此操作) .
关于堆栈与堆的更多信息:https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/
我是 c++ 的新手,我正面临 std::cout
的一种我不理解的奇怪行为。特别是,当我想使用 cout << nd.next[2]->next[17]->val
打印第二个节点的值时,我得到了一些复杂的字节。但是,如果我先将它设置为一个变量,例如 string let2 = nd.next[2]->next[17]->val
,然后使用 cout << let2
,它会打印出正确的字符。我的代码在下面,我正在实施一个特里。 (此外,由于我对 C++ 还很陌生,因此我感谢您对我在代码中做错的任何其他评论)
#include <iostream>
#include <set>
#include <iterator>
#include <map>
#include <string>
#include <unordered_map>
using std::set;
using std::cout;
using std::endl;
using std::string;
struct Node {
Node* next[26];
string val;
void insert(string str) {
cout << "insert " << str << endl;
insert(str, 0);
}
void insert(string str, int idx) {
if (idx >= str.length()) {
return;
}
char cur = str[idx];
int curIdx = cur - 'a';
cout << "cur: " << cur << endl;
cout << "cur idx: " << curIdx << endl;
if (!next[curIdx]) {
Node newNode = Node();
newNode.val = cur;
next[curIdx] = &newNode;
}
next[curIdx]->insert(str, idx+1);
}
};
int plus(int a, int b) {
return a+b;
}
int main() {
Node nd = Node();
nd.insert("cryptography");
string let1 = nd.next[2]->val;
string let2 = nd.next[2]->next[17]->val;
cout << "first letter " << let1 << endl; // c
cout << "second letter " << nd.next[2]->next[17]->val << endl; // wrong
cout << "second letter " << let2 << endl; // work as expected
cout << "sum " << plus(1,2) << endl; // work as expected
// cout << nd.next[2]->next[17]->val << endl;
return 0;
}
关于问题的第二部分 ("what I am doing wrong"),在 insert()
方法中,您在堆栈上创建 Node()
对象并使用指向此对象的指针分配 next[curIdx]
目的。但是一旦执行超出定义该对象的范围,该堆栈对象就会自动销毁,因此 next[curIdx]
最终指向垃圾(对象在销毁之前曾经所在的内存)。
不确定下一行是如何工作的,next[curIdx]
此时指向垃圾:next[curIdx]->insert(str, idx+1);
相反,您应该使用 new
运算符在堆上分配 Node 对象,例如:
if (!next[curIdx]) {
next[curIdx] = new Node(); // allocated on heap
next[curIdx]->val = cur;
}
但是你应该确保在某个时候释放(delete
)它们以避免内存泄漏。 Node 的析构函数可能是一个很好的地方——你可以递归地 delete
来自下一个数组的所有非空节点。
您也可以使用 smart pointers 而不是原始指针,它们会在无法再访问对象时自动删除对象(垃圾收集器会在 Java 和 C# 等其他语言中自动执行此操作) .
关于堆栈与堆的更多信息:https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/