难以理解两个相同类型的单独结构指针的内存分配在一个示例中有效,但在另一个示例中无效

问题描述

我很难理解内存分配的情况,这两种特定的情况产生不同的结果,但是在应用我的天真智慧时,功能在我看来是相同的。我在下面创建了一个简化的异类代码示例,以演示我遇到的问题。我很高兴看到数据以一种过于复杂的方式传递给函数,但是除非有根本缺陷,否则请假定它是必要的。

在注释代码的第一部分。这有效,没有问题。 在注释代码的第二部分中,终端闪烁一会儿,并且退出时没有错误或警告。

我非常感谢理解为什么会这样。显然我还有很多东西要学习!

在此先感谢

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;});

额外的注释:

  1. 您的第二个版本与第一个版本具有相同的功能,但是增加了内存泄漏。您调用malloc并立即覆盖指向新分配的内存的指针,并丢失该指针。
  2. 请勿在C ++中使用malloc(除非之后您准备使用放置new)。分配内存的C ++方法是使用newdelete
  3. 避免在现代C ++中使用newdelete。我们有smart pointerscontainers为我们做到这一点。在C ++ 11中,几乎没有需要new的地方,在C ++ 14中,它已经有点难闻的气味。
  4. struct item *是一种C主义。您无需在C ++中重复使用struct关键字,item* item_1_pointer = nullptr;就可以正常工作。
  5. 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++;
        }
    }

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...