在"短",我priority_queue
选择满足特定条件的k unordered_set<int>
。我想将它们(哈希集)作为queue
返回。
由于priority_queue
的创建和维护期望元素交换,我使用指针而不是unordered_set<int>
作为priority_queue
的条目。
因此,返回类型应为queue< smart_ptr<unordered_set<int>> >
。
如果我使用shared_ptr
代码正常,但我希望使用unique_ptr
,因为它更经济,客户承诺将其用作unique_ptr
。
如何使用unique_ptr
来实现以下代码?
-------------------详细说明-------------------------- -----
我有一个函数可以从文件中读取保留k
行,这些行的大小最接近参考大小。比方说,如果k=2
,引用大小为5
,则文件包含6行大小(此行中的整数数)3,5,6,20,2,1
。 k-closest
行分别是大小为5
和6
的两行。
我使用priority_queue
大小为k
的自定义比较器来实现目标。我决定返回包含所选queue
行的k-closest
,因为客户端不想知道比较器是如何实现的(比较器是priority_queue
模板的参数)。 / p>
using ptr_type = shared_ptr<unordered_set<int>>;
// ???????????????????????????????????????
// using ptr_type = unique_ptr<unordered_set<int>>; // unique_ptr does not work
// ???????????????????????????????????????
// Is it possible to transfer unique_ptr entries from a priority_queue to a queue?
using pair_comm_type = pair<int,ptr_type>;
queue<pair_comm_type> f() {
// myFile.txt is a space separated file of integers.
// Different lines may have different lengths (number of integers)
string inputFile = "myFile.txt";
const int TOP_K_LINE = 3;
// to open a file
ifstream fin(inputFile.c_str());
string readBuffer;
// The file opened
// to define a priority_queue
// define customized compare function, such that retained lines have size
// closest to the reference value.
double referenceSize = log10(10.0);
auto comp = [&referenceSize](const pair_comm_type &LHS, const pair_comm_type &RHS)
{ return abs(log10(LHS.first)-referenceSize)
< abs(log10(RHS.first)-referenceSize); };
priority_queue<pair_comm_type, vector<pair_comm_type>, decltype(comp)> myHeap(comp);
// the priority_queue defined
int bufIntValue = -1;
int curMinArraySize = -1; // auxilliary variable, to reduce heap top access
// to read the file line by line
while (getline(fin,readBuffer)) {
// to read int in each line to a hash set
istringstream S(readBuffer);
ptr_type lineBufferPtr(new unordered_set<int>);
while (S>>bufIntValue) lineBufferPtr->insert(bufIntValue);
// one line read
// to decide retain or not based on the length of this line
int arraySize = lineBufferPtr->size();
if (myHeap.size() < TOP_K_LINE) {
// We can add new lines as long as top-k is not reached
myHeap.emplace(arraySize,std::move(lineBufferPtr));
curMinArraySize = myHeap.top().first;
continue;
}
if (arraySize <= curMinArraySize) continue;
myHeap.emplace(arraySize,std::move(lineBufferPtr));
myHeap.pop();
curMinArraySize = myHeap.top().first;
}
// all lines read
fin.close();
// to transfer values from the priority_queue to a queue
// ???????????????????????????????????????
// Is it possible that we can make changes here such that unique_ptr can also work??????
// ???????????????????????????????????????
queue<pair_comm_type> Q;
while (!myHeap.empty()) {
auto temp = myHeap.top();
myHeap.pop();
Q.emplace(temp.first,std::move(temp.second));
}
/*
while (!Q.empty()) {
printf("%d, ",Q.front().first);
Q.pop();
}
printf("\n");
*/
return Q;
}
答案 0 :(得分:0)
STL
容器旨在移动,当您这样做时,它与使用指针一样高效。事实上,他们在内部使用指针,所以你不必。
我会考虑使用这样的值:
using pair_comm_type = pair<int, unordered_set<int>>;
queue<pair_comm_type> f() {
string inputFile = "myFile.txt";
const int TOP_K_LINE = 3;
ifstream fin(inputFile.c_str());
string readBuffer;
double referenceSize = log10(10.0);
auto comp = [&referenceSize](const pair_comm_type &LHS, const pair_comm_type &RHS)
{ return abs(log10(LHS.first)-referenceSize)
< abs(log10(RHS.first)-referenceSize); };
priority_queue<pair_comm_type, vector<pair_comm_type>, decltype(comp)> myHeap(comp);
int bufIntValue = -1;
int curMinArraySize = -1;
while (getline(fin,readBuffer)) {
istringstream S(readBuffer);
// no need to use pointers here
unordered_set<int> lineBufferPtr;
while (S>>bufIntValue)
lineBufferPtr.insert(bufIntValue);
int arraySize = lineBufferPtr.size();
if (myHeap.size() < TOP_K_LINE) {
myHeap.emplace(arraySize,std::move(lineBufferPtr));
curMinArraySize = myHeap.top().first;
continue;
}
if (arraySize <= curMinArraySize) continue;
myHeap.emplace(arraySize,std::move(lineBufferPtr));
myHeap.pop();
curMinArraySize = myHeap.top().first;
}
fin.close();
// Use std::move to transfer the top() element which will be
// just as efficient as using pointers
queue<pair_comm_type> Q;
while (!myHeap.empty()) {
auto temp = std::move(myHeap.top()); // USE MOVES
myHeap.pop();
Q.push(std::move(temp));
}
return Q;
}
答案 1 :(得分:0)
@Galik的解决方案有效。
至于原来的问题,简单的答案是否定的。我们无法从priority_queue中传输unique_ptr。
unique_ptr
的{{3}},其参数是const引用,将被删除。 priority_queue::top()
的返回类型为copy constructor。因此,我们不能使用返回值来创建新的unique_ptr
对象。