是否将对main()中的局部变量的引用传递给其他线程/函数的不良做法?

问题描述 投票:0回答:2

考虑下面的示例,在该示例中我在specialNumber中创建局部变量main(),并通过引用将其传递给新线程以及另一个函数(请忽略缺少锁/互斥体的方式:]

#include <iostream>
#include <thread>

void threadRun(int& number) {
    while(true) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << number << std::endl;
        number += 1;
    }
}

int main() {
    int specialNumber = 5;
    std::thread newThread(threadRun, std::ref(specialNumber));
    otherFunction(specialNumber);
    newThread.join();
}


void otherFunction(int& number) {
    // does something with number
}

我知道,通常应该避免传递对局部变量的引用,因为一旦函数终止该变量将超出范围,并且引用将无效。

但是,由于变量是main()的局部变量,并且该函数直到整个程序终止后才会终止,所以这种做法有什么问题吗?

我的特定用例将在此处存储一个小对象(主要由指向堆对象的指针以及辅助函数组成),该对象将由多个线程和/或函数使用,并传递对其的引用。我知道一种替代方法是使用诸如shared_ptr的智能指针将其存储在堆中,但是以这种方式存储如此小的对象对我而言似乎效率低下。

我很抱歉,如果我的任何术语不正确,我对C ++还是陌生的。请纠正我!

c++ memory pass-by-reference
2个回答
4
投票

您的假设

我知道通常应该避免传递对局部变量的引用

似乎没有根据。

传递对函数的引用没有错。但是,引用对象的函数不应拥有该对象的所有权。该函数不应假定所引用的对象在退出后仍继续存在。

这不同于returning对局部变量的引用,这总是错误的。

我认为传递对线程的引用没有问题(没有同步),这通常优于使用全局变量的替代方法。

[智能指针,例如std::shared_ptr,仅在假定函数具有对象的(共享)所有权时才需要。如果threadRun想要在对象退出后保留对其的引用/指针。


0
投票

只要main()线程处于活动状态,就不会出现问题。

但是我想详细说明std::ref()的用法。 std::ref()的用途之一就是正在编码的场景。

使用std::ref()时,实际上是在返回可以复制的std::reference_wrapper。引用包装可以存储在容器中,而普通引用则不能。

通过引用将对象传递给线程的构造函数是使用引用包装器并且std::ref()返回引用包装器的一种方法。

如果您传递了简单的参考文献,将会看到不同的行为。

阅读有关std::ref()std::reference_wrapper的更多信息

此线程How is tr1::reference_wrapper useful?也很有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.