- 主题:关于c++的右值引用的一个问题
线程池源码连接
https://github.com/ppwwyyxx/sigmod14contest/blob/85738897900b95ed64821ce8ad1e1e6d5a132eda/src/lib/ThreadPool.hh
我写的测试程序
int main() {
CClassTestA cta;
cta.add();
}
class CClassTestA
{
public:
CClassTestA(){p = new ThreadPool(6);};
~CClassTestA(){delete p;};
int test() { printf("this is CClassTestA::test\n"); return 3; };
int test1(int a, int b)
{
printf("this CClassTestA::test,result = %d\n", a + b);
return a + b;
};
void test2(int a)
{
printf("this CClassTestA::test2,result = %d\n", a );
//return a ;
};
void add()
{
m_d = std::bind(&CClassTestA::test2, this, std::placeholders::_1);
m_e = std::bind(&CClassTestA::test, this);
//p->enqueue(std::bind(&CClassTestA::test, this), std::bind(&CClassTestA::test2, this, std::placeholders::_1));
p->enqueue(m_e, m_d);
};
private:
ThreadPool *p;
std::function<void(int)> m_d;
std::function<int()> m_e;
};
下面这行执行会引发报错,绑定的函数指针飞了
p->enqueue(std::bind(&CClassTestA::test, this), std::bind(&CClassTestA::test2, this, std::placeholders::_1));
但是,p->enqueue(m_e, m_d);就不报错。我猜测是右值引用生命周期的问题,但是不清楚哪里出了问题,但是我想报错那样的写法才是正常使用状态,麻烦大家看看哪出的问题?谢谢
--
FROM 115.171.170.*
ThreadPool会在CClassTestA之前删除,ThreadPool删除之前会join等线程执行完。
【 在 here080 的大作中提到: 】
: 你的ThreadPool直接就删除了,里面的内容当然会出问题吧。
:
--
FROM 115.171.170.*
代码都贴出来了,你可以自己看
【 在 here080 的大作中提到: 】
: 你确定?一般ThreadPool要求手动join吧?
:
--
FROM 115.171.170.*
这不就是为了学习这块的语法知识吗?我觉得问题在
template<class Function, class Callback>
void enqueue(Function &&f, Callback &&callback, int priority = 5) {
auto task = std::make_shared<std::function<void()>>(
std::bind(__ThreadPoolImpl::runner_wrapper,
std::make_shared<__ThreadPoolImpl::runner<Function, Callback>>(
std::forward<Function>(f), std::forward<Callback>(callback))));
//auto task = std::make_shared<std::function<void()>>(std::bind(std::forward<Callback>(callback), (std::forward<Function>(f))()));
{
std::lock_guard<std::mutex> lock(queue_mutex);
tasks.emplace(priority, std::bind(__ThreadPoolImpl::task_wrapper, task));
}
condition.notify_one();
}
不用右值,修改成 template<class Function, class Callback>
void enqueue(Function f, Callback callback, int priority = 5)
也一样有错,但是这里到底哪错了
【 在 here080 的大作中提到: 】
: 贴出来了个毛球。
: 我还以为你用的啥正常的第三方库。
: 结果是你们自己搞的小作坊ThreadPool,代码问题就出在那里面。各种滥用右值引用和shared_ptr
: ...................
--
FROM 115.171.170.*
变量右值赋值之后不可再用,这些都知道
写成成员变量的方式是为了测试,那样才不会报错,等于把左值赋值给右值函数才没报错,直接赋值右值
p->enqueue(std::bind(&CClassTestA::test, this), std::bind(&CClassTestA::test2, this, std::placeholders::_1));
就会报错。
这里感觉对右值语义没理解透,所以来请教到底哪里出的问题?
【 在 here080 的大作中提到: 】
: 如无特殊情况,不要使用右值引用作为成员变量。
:
--
FROM 115.171.170.*
你搞明白我问的问题了吗?
你说这些简单的语法语义学过的都知道。
我也知道是ThreadPool得问题
现在就是再问是ThreadPool哪的问题。
【 在 here080 的大作中提到: 】
: 成员变量引用临时变量,然后之后再用时临时变量已经没有了。
: 你不要反复贴这句。我说了,这个问题是那个ThreadPool的实现问题。
: 我说的右值引用作为成员变量是指那里面的东西。
: ...................
--
FROM 115.171.170.*
你说的语法语义都知道,根本就不是问的这个
你说的有问题的写法跑起来是对的
没问题的写法跑起来是错的,所以我才来问怎么解释
如果你真明白
把你认为正确的代码写出,是不是语法语义都正确,跑起来也没问题。
跑一跑就知道了
【 在 xunery 的大作中提到: 】
: 你搞明白我问的问题了吗?
: 你说这些简单的语法语义学过的都知道。
: 我也知道是ThreadPool得问题
: ...................
--
FROM 115.171.170.*
先感谢你打了这么多字
我跑了下你的代码
x->f(); // Error
跑了下这行也没用错误。
make_bad函数接受右值参数,
auto x = make_bad(std::bind(foo, 3));
这行传入的就是右值参数,我理解这样写没啥问题
为何说这个是错的?
跑起来x,y都没错
【 在 here080 的大作中提到: 】
: \_(ツ)_/
: 小朋友,你要问问题,就该是你把问题的实质提取出来。
: 你贴了一段代码,但问题的实质根本不在这段代码之中,还要逼人去github上读小作坊ThreadPool的实现。
: ...................
--
FROM 115.171.170.*
如果是左值引用,这种写法肯定是不对的
但是因为是右值引用,不需要bind那个临时变量实体
这不就是典型的右值引用的用法么
相反auto y = make_bad(member);这句把一个左值传给一个接受右值引用参数的函数,正规不是应该写成auto y = make_bad(move(member));这样么
【 在 here080 的大作中提到: 】
: C++里错误程序不一定跑起来会挂。准确地说这是UB,编译器有可能因为某些行为没有触发错误。
: leetcode你知道吗?你可以把这段代码放到它家的playground上去跑一下,错误很清楚。
: 你既然跑了,那两行cout看了没?
: ...................
--
FROM 115.171.170.*
谢谢,因为右值引用有延长临时变量生命周期的作用,原来对这里理解有偏差,现在完全明白了。
你这段英文是从哪里摘抄的,我原来就没有找到这么明确的表述说明这个问题
【 在 bihai 的大作中提到: 】
: 右值引用和左值引用都只是引用,不是左值本身,所以没有本身的内存空间。只有一些例外,比如赋值给const参考或者右值可以延长生命期,但是,在构造函数时是双重例外了,只在延长寿命到构造函数结束。
: a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists. (note: such initialization is ill-formed as of DR 1696).
:
--
FROM 115.171.170.*