C++:如何正确地将 deque::front() 返回的变量传递出函数?
C++: how to properly pass a variable returned by deque::front() out of a function?
我正在开发一个多线程程序,其中 "std::deque< MyObject > myBuffer" 用作 FIFO 缓冲区,生产者线程使用 push_back() 不断将自定义对象添加到双端队列的末尾,并且消费者线程使用辅助函数来检索对象并处理同步和互斥锁。
std::deque< MyObject > myBuffer;
std::mutex mtx;
int main() {
std::thread producerThread(producer());
std::thread consumerThread(consumer());
// other code
return 0;
}
生产者函数:
void producer() {
while (somecondition) {
// code producing MyObject object
std::lock_guard<std::mutex> lck(mtx);
myBuffer.push_back(object);
}
}
消费者函数:
void consumer() {
while(somecondition) {
MyObject object1, object2;
if (retrieve(object1)) {
// process object1
}
if (retrieve(object2)) {
// process object2
}
}
}
我当前的辅助函数如下所示:
bool retrieve(MyObject & object) {
// other code ...
std::lock_guard<std::mutex> lck(mtx);
if (!myBuffer.empty()) {
object = myBuffer.front();
myBuffer.pop_front();
return true;
} else {
return false;
}
}
不过,我很快意识到deque::front() returns容器中第一个元素的引用。 "object" 是 MyObject&,所以根据我的理解,只有双端队列中第一个元素的引用被传递给对象,因此当我调用 pop_front() 时,引用的元素应该是消失了,对象变量持有无效引用。令人惊讶的是,当我实际 运行 代码时,一切都与我预期的相反。那么谁能帮我理解 "deque::front() returns the reference" 是如何工作的?谢谢。
我不明白你的目的,也许你可以试试deque::at()
pop_front() 从队列中移除第一个元素。它不会删除对象。因此,在 pop_front() 调用之后引用对象应该有效。
更新-
#include <iostream>
#include <queue>
#include <algorithm>
class newClass {
public:
newClass () {
}
~newClass () {
std::cout << " Destructor is called. " << "\n";
}
newClass(const newClass &obj) {
std::cout << "Copy is called." << "\n";
}
void print(void) {
std::cout << "Hi there !" << "\n";
}
};
void queueWithPointer(void) {
std::deque<newClass *> deque;
deque.push_back(new newClass());
deque.push_front(new newClass());
newClass *b = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
b->print();
}
void queueWithObjects(void) {
std::deque<newClass> deque;
deque.push_back(newClass());
deque.push_front(newClass());
newClass ba = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
ba.print();
}
int main()
{
queueWithPointer();
// queueWithObjects();
return 0;
}
以上程序可用于理解行为。对于对象,调用复制构造函数并将新副本存储在双端队列中。当 pop_front() 被调用时,副本被删除。而在指针的情况下,地址被复制。因此,删除的是地址,而不是地址引用的实际对象。你会发现在这种情况下并没有调用析构函数。
它工作正常,这是预期的行为。
您不分配引用 - 您不能,C++ 引用是不可变的。您实际上复制了该值。这就是它应该如何工作的。当 foo
是引用时 foo = ...
赋值的语义大致是:
"copy the right-hand value to the place referenced by foo
".
当右侧有引用时,复制引用的值
在你的例子中,object = myBuffer.front();
行将 deque 的前端值复制到 consumer()
中的变量 object1
或 object2
,分别到调用。稍后调用 .pop_front()
会破坏双端队列中的值,但不会影响已复制的值。
我正在开发一个多线程程序,其中 "std::deque< MyObject > myBuffer" 用作 FIFO 缓冲区,生产者线程使用 push_back() 不断将自定义对象添加到双端队列的末尾,并且消费者线程使用辅助函数来检索对象并处理同步和互斥锁。
std::deque< MyObject > myBuffer;
std::mutex mtx;
int main() {
std::thread producerThread(producer());
std::thread consumerThread(consumer());
// other code
return 0;
}
生产者函数:
void producer() {
while (somecondition) {
// code producing MyObject object
std::lock_guard<std::mutex> lck(mtx);
myBuffer.push_back(object);
}
}
消费者函数:
void consumer() {
while(somecondition) {
MyObject object1, object2;
if (retrieve(object1)) {
// process object1
}
if (retrieve(object2)) {
// process object2
}
}
}
我当前的辅助函数如下所示:
bool retrieve(MyObject & object) {
// other code ...
std::lock_guard<std::mutex> lck(mtx);
if (!myBuffer.empty()) {
object = myBuffer.front();
myBuffer.pop_front();
return true;
} else {
return false;
}
}
不过,我很快意识到deque::front() returns容器中第一个元素的引用。 "object" 是 MyObject&,所以根据我的理解,只有双端队列中第一个元素的引用被传递给对象,因此当我调用 pop_front() 时,引用的元素应该是消失了,对象变量持有无效引用。令人惊讶的是,当我实际 运行 代码时,一切都与我预期的相反。那么谁能帮我理解 "deque::front() returns the reference" 是如何工作的?谢谢。
我不明白你的目的,也许你可以试试deque::at()
pop_front() 从队列中移除第一个元素。它不会删除对象。因此,在 pop_front() 调用之后引用对象应该有效。
更新-
#include <iostream>
#include <queue>
#include <algorithm>
class newClass {
public:
newClass () {
}
~newClass () {
std::cout << " Destructor is called. " << "\n";
}
newClass(const newClass &obj) {
std::cout << "Copy is called." << "\n";
}
void print(void) {
std::cout << "Hi there !" << "\n";
}
};
void queueWithPointer(void) {
std::deque<newClass *> deque;
deque.push_back(new newClass());
deque.push_front(new newClass());
newClass *b = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
b->print();
}
void queueWithObjects(void) {
std::deque<newClass> deque;
deque.push_back(newClass());
deque.push_front(newClass());
newClass ba = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
ba.print();
}
int main()
{
queueWithPointer();
// queueWithObjects();
return 0;
}
以上程序可用于理解行为。对于对象,调用复制构造函数并将新副本存储在双端队列中。当 pop_front() 被调用时,副本被删除。而在指针的情况下,地址被复制。因此,删除的是地址,而不是地址引用的实际对象。你会发现在这种情况下并没有调用析构函数。
它工作正常,这是预期的行为。
您不分配引用 - 您不能,C++ 引用是不可变的。您实际上复制了该值。这就是它应该如何工作的。当 foo
是引用时 foo = ...
赋值的语义大致是:
"copy the right-hand value to the place referenced by foo
".
当右侧有引用时,复制引用的值
在你的例子中,object = myBuffer.front();
行将 deque 的前端值复制到 consumer()
中的变量 object1
或 object2
,分别到调用。稍后调用 .pop_front()
会破坏双端队列中的值,但不会影响已复制的值。