aigebiu
V2EX  ›  C

在学 C++ 有个问题

  •  
  •   aigebiu · Mar 7, 2016 · 3174 views
    This topic created in 3892 days ago, the information mentioned may be changed or developed.

    void foo() {}

    thread(&foo);
    结果报错 error: ‘ foo ’ declared as reference but not initialized

    a = thread(&foo);
    把它赋给一个 thread 类型变量 a ,就编译通过了

    或者
    thread a(&foo);
    也能通过

    为什么呢?谢谢

    21 replies  •  2016-03-08 20:48:58 +08:00
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    1
    又试了下 thread(&foo).join() 也能过 好像只要把初始化好的 thread 对象用在任何一个地方 (赋值右边,调用方法) 就能过……
    bengol
    bengol
    Mar 7, 2016 via Android
    2
    贴编译器版本
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    3
    @bengol gcc version 4.8.4
    patrickstar
    patrickstar
    Mar 7, 2016
    4
    不是直接 std::thread(foo)就可以了吗,为啥子在函数名 foo 前加个&
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    5
    诶我好像明白错误提示的意思了。。
    编译器把它解释为 thread &foo; 了 声明一个引用但没初始化 所以报错。。

    error: ‘ foo ’ declared as reference but not initialized
    thread &foo;

    error: ‘ foo ’ declared as reference but not initialized
    thread(&foo);

    那么问题就变成了 为什么会解析成声明呢?
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    6
    @patrickstar 嗯 是…… 但是显式地取地址也可以吧?
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    7
    难道类(变量) 也是一种声明变量的方式?
    比如 string(a); 也能过 得到一个空字符串 a (之前没声明 a )
    patrickstar
    patrickstar
    Mar 7, 2016
    8
    一般情况下函数名本身就是一个指针,再取地址就是指针的指针,不是 std::thread() 需要的参数
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    9
    @patrickstar 可是&后也能正常运行啊 函数指针取不取地址应该是一样的(只有在访问成员函数时好像有区别)

    贴个 stackoverflow 上的答案( http://stackoverflow.com/questions/4298654/operator-optional-in-function-pointer-assignment )

    Operator & is indeed optional when taking the address of a function in your context (assigning it to something). It is not compiler-specific, it follows from the formal definition of the language.

    Symmetrically, operator * is optional when invoking the function through a pointer. In your example, you could invoke the function as either (*logfunc)(n) or logfunc(n). You used the latter, but the former would work as well.
    ffffwh
    ffffwh
    Mar 7, 2016 via Android
    10
    C++语法二义性很多的。
    这种情况会优先判为 declaration 而不是函数调用,好在一般都有编译器 warning
    matthewgao
    matthewgao
    Mar 7, 2016 via Android
    11
    你这里还有个问题,如果你只写 thread(foo),那么你生成的这个 thread 对象就是个右值对象,没有任何产量标识它,那么它一旦 go out of scope 那么就会 segmentalfault, 但是你写 thread(foo).join 会阻塞主进程,所以线程会正常运行
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    12
    @matthewgao 哦 谢谢 那 c ++里有没有像 go 语言里的 go 那样的轻量级并发呢?我是一个线程不断读数据 然后动态创建若干线程处理数据 是不是只能维护一个线程池 主线程终止时统一 join 呢?

    @ffffwh 为什么会优先判为 declaration ?有没有这方面资料、书推荐呢?谢谢
    vanxining
    vanxining
    Mar 7, 2016
    13
    学习了。我想应该是语法优先级的问题。就像 C++11 之前的 vector<vector<int>>以及 Foo foo(int);这样的情况一样。
    bombless
    bombless
    Mar 7, 2016 via Android
    14
    噗 c++本身是不支持嵌套的函数定义的,所以本身函数调用和函数定义是不会在一个层次里出现的。
    你这个是 gcc 扩展。
    vanxining
    vanxining
    Mar 7, 2016
    15
    @vanxining 想了想,令人容易搞错的这种形式:
    Foo bar();。
    这是一个函数声明还是定义了一个 Foo 实例?
    congeec
    congeec
    Mar 7, 2016
    16
    @patrickstar 函数名就是函数指针,加个取地址符号&还是函数指针。这是特例
    xuboying
    xuboying
    Mar 7, 2016 via Android
    17
    插个楼,这里的函数可以用 lambda 定义么?
    aigebiu
    aigebiu
    OP
    Mar 7, 2016
    18
    @bombless 我用 clang 编译也是同样的错诶 我觉得还是把&判断成声明引用了
    matthewgao
    matthewgao
    Mar 8, 2016 via Android
    19
    @xuboying 当然可以啦
    matthewgao
    matthewgao
    Mar 8, 2016 via Android
    20
    @aigebiu 这个看你具体需求了,不 join detach 也可以,如果你这一堆线程都只干这一个事
    bombless
    bombless
    Mar 8, 2016 via Android
    21
    @aigebiu clang 和 gcc 是兼容的。主楼说的没什么错,我是说普通编译器并不会遇到这个问题,而会在别的地方报错。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4896 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 03:47 · PVG 11:47 · LAX 19:47 · JFK 22:47
    ♥ Do have faith in what you're doing.