如何在不删除元素的情况下从SystemVerilog队列移除元素
SystemVerilog队列移除中间元素(保留对象)
首先澄清一个关键误解:SystemVerilog中delete(index)方法只会移除队列中对应位置的引用,并不会销毁类对象本身。对象的生命周期由所有指向它的引用决定,只要还有其他队列(比如你的my_other_q)持有该对象的引用,对象就会一直存在。你之前担心的“delete会删除对象”是不存在的,直接用delete(index)其实是最直接高效的方案。
方案1:直接使用delete(index)
修改你的函数即可,加上边界检查避免越界错误:
function void remove_my_q_element(int index); if(index >= 0 && index < my_q.size()) my_q.delete(index); endfunction
执行后,my_q中不再包含该对象的引用,但my_other_q里的引用依然有效,对象本身不会被销毁。
方案2:队列切片拼接
如果你偏好不用delete,可以利用SystemVerilog队列的切片特性,将目标位置前后的元素重新拼接成新队列:
function void remove_my_q_element(int index); if(index >= 0 && index < my_q.size()) begin if(index == 0) my_q = my_q[1:$]; // 移除第一个元素 else if(index == my_q.size()-1) my_q = my_q[0:index-1]; // 移除最后一个元素 else my_q = my_q[0:index-1] + my_q[index+1:$]; // 移除中间元素 end endfunction
这种方式同样只是移除队列中的引用,对象本身不受影响。队列的切片操作是底层优化过的,不需要手动复制所有元素,效率和delete相当。
效果验证示例
可以添加打印代码验证对象状态:
class myclass; int id; function new(int val); id = val; endfunction endclass myclass my_q[$]; myclass my_other_q[$]; module tb; initial begin myclass a = new(10); my_q.push_back(a); my_other_q.push_back(a); $display("移除前:my_q长度=%0d, my_other_q长度=%0d", my_q.size(), my_other_q.size()); $display("my_q中对象ID:%0d, my_other_q中对象ID:%0d", my_q[0].id, my_other_q[0].id); remove_my_q_element(0); $display("移除后:my_q长度=%0d, my_other_q长度=%0d", my_q.size(), my_other_q.size()); if(my_other_q.size() > 0) $display("my_other_q中对象仍存在,ID:%0d", my_other_q[0].id); end function void remove_my_q_element(int index); my_q.delete(index); endfunction endmodule
仿真输出会显示my_q长度变为0,而my_other_q仍持有对象,且对象ID可正常访问,证明对象未被销毁。
内容的提问来源于stack exchange,提问作者Melandru's Square
相关产品推荐
相关产品推荐

