如何解决难以理解两个相同类型的单独结构指针的内存分配在一个示例中有效,但在另一个示例中无效
我很难理解内存分配的情况,这两种特定的情况产生不同的结果,但是在应用我的天真智慧时,功能在我看来是相同的。我在下面创建了一个简化的异类代码示例,以演示我遇到的问题。我很高兴看到数据以一种过于复杂的方式传递给函数,但是除非有根本缺陷,否则请假定它是必要的。
在注释代码的第一部分。这有效,没有问题。 在注释代码的第二部分中,终端闪烁一会儿,并且退出时没有错误或警告。
我非常感谢理解为什么会这样。显然我还有很多东西要学习!
在此先感谢
Matminster。
#include <iostream>
#include <list>
struct item{
int item_ID;
std::list<int> related_item_IDs;
};
struct item * return_item_details(std::list<item> list_of_items,int item_ID) {
for(std::list<item>::iterator it = list_of_items.begin(); it != list_of_items.end(); it++) {
if(it->item_ID == item_ID) {
return & * it;
}
}
return NULL;
}
int find_shared_related_items(int item_1_ID,int item_2_ID,std::list<item> list_of_items) {
int total_shared_items=0;
//This works_________________________________________________________________
// struct item * item_1_pointer = return_item_details(list_of_items,item_1_ID);
// struct item * item_2_pointer = return_item_details(list_of_items,item_2_ID);
//___________________________________________________________________________
//But not this?________________________________________________________________
// struct item * item_1_pointer = (struct item * ) malloc(sizeof(struct item * ));
// item_1_pointer = return_item_details(list_of_items,item_1_ID);
// struct item * item_2_pointer = (struct item * ) malloc(sizeof(struct item * ));
// item_2_pointer = return_item_details(list_of_items,item_2_ID);
// //_____________________________________________________________________________
for(std::list<int>::iterator it = item_1_pointer->related_item_IDs.begin(); it != item_1_pointer->related_item_IDs.end(); it++) {
for(std::list<int>::iterator it2 = item_2_pointer->related_item_IDs.begin(); it2 != item_2_pointer->related_item_IDs.end(); it2++) {
if( * it == * it2) {
total_shared_items++;
}
}
}
return total_shared_items;
}
int main() {
item item_1;
item_1.item_ID = 1;
item_1.related_item_IDs.push_back(3);
item_1.related_item_IDs.push_back(4);
item_1.related_item_IDs.push_back(5);
item_1.related_item_IDs.push_back(6);
item item_2;
item_2.item_ID = 2;
item_2.related_item_IDs.push_back(5);
item_2.related_item_IDs.push_back(6);
item_2.related_item_IDs.push_back(7);
item_2.related_item_IDs.push_back(8);
std::list<item> list_of_items;
list_of_items.push_back(item_1);
list_of_items.push_back(item_2);
std::cout << "The total number of shared items between item " << item_1.item_ID << " and item " << item_2.item_ID << " is: " << find_shared_related_items(item_1.item_ID,item_2.item_ID,list_of_items) << "\n";
return 0;
}
解决方法
第一个版本因不幸而运作。这是不确定的行为。
在return_item_details
中,您可以按值接受std::list
,这意味着该列表及其所有元素将被复制,并在函数完成后将其销毁。然后,您返回这些临时元素之一的地址并尝试使用它(但该元素不再存在)。
您可以更改要通过引用传递的参数:
struct item * return_item_details(std::list<item>& list_of_items,int item_ID) {
// ~~~~~~~~~~~~~~~^
或者改用<algorithm>
库中的std::find_if
:
auto item_1_iter = std::find_if(list_of_items.begin(),list_of_items.end(),[item_1_ID](auto& listElem){return listElem.item_ID == item_1_ID;});
额外的注释:
- 您的第二个版本与第一个版本具有相同的功能,但是增加了内存泄漏。您调用
malloc
并立即覆盖指向新分配的内存的指针,并丢失该指针。 - 请勿在C ++中使用
malloc
(除非之后您准备使用放置new
)。分配内存的C ++方法是使用new
和delete
。 - 避免在现代C ++中使用
new
和delete
。我们有smart pointers和containers为我们做到这一点。在C ++ 11中,几乎没有需要new
的地方,在C ++ 14中,它已经有点难闻的气味。 -
struct item *
是一种C主义。您无需在C ++中重复使用struct
关键字,item* item_1_pointer = nullptr;
就可以正常工作。 -
auto
是C ++ 11中引入的一种非常方便的机制,它可能允许您显式地跳过键入std::list<item>::iterator
(以及编译器可以从上下文中推断出的任何其他类型):
for(auto it = item_1_pointer->related_item_IDs.begin(); it != item_1_pointer->related_item_IDs.end(); it++) {
for(auto it2 = item_2_pointer->related_item_IDs.begin(); it2 != item_2_pointer->related_item_IDs.end(); it2++) {
if( * it == * it2) {
total_shared_items++;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。