求教个神奇的 C++ 打印问题

Betsy · 2024-8-5 23:56:48 · 352 次点击
### 代码

```c++
#include <iostream>
#include <vector>
#include <cstdint>
#include <optional>

using GroupId = std::uint64_t;
using ReducedGroupId = GroupId;

struct Memo {
    std::optional<ReducedGroupId> GetReduceGroupId(const GroupId& group_id) {
        // omit
        return std::make_optional<ReducedGroupId>(group_id);
    }
};

int main(int argc, char* argv[]) {
    std::vector<GroupId> tmp;

    Memo memo;
    GroupId group_id = 1;
    const ReducedGroupId& reduced_group_id = memo.GetReduceGroupId(group_id).value();
    std::cout << "3.1.->|" << reduced_group_id << ":" << &reduced_group_id << std::endl;

    tmp.push_back(4);
    std::cout << "3.2.->|" << reduced_group_id << ":" << &reduced_group_id << std::endl;

    tmp.push_back(5);
    std::cout << "3.3.->|" << reduced_group_id << ":" << &reduced_group_id << std::endl;
    return 0;
}

```

### 结果

```text
3.1.->|1:0x7ffe4fcd3530
3.2.->|4:0x7ffe4fcd3530
3.3.->|5:0x7ffe4fcd3530
```

### 问题

- 3.1, 3.2, 3.3 为啥打印结果不一样?
举报· 352 次点击
登录 注册 站外分享
16 条回复  
realJamespond 小成 2024-8-6 18:25:19
右值是个很抽象的东西一直没搞清楚
ipwx 小成 2024-8-6 11:25:15
额,楼主你这

    std::optional<ReducedGroupId> GetReduceGroupId(const GroupId& group_id) {
        // omit
        return std::make_optional<ReducedGroupId>(group_id);
    }

不是取了  group_id 的地址塞到 optional 里面。optional 本来就是个完整的对象,所以你是复制了一份 group_id 塞到了 optional 里面。

然后

const ReducedGroupId& reduced_group_id

取的就是这个临时的 optional 内部的 int64 的地址,当然这句话执行完就被 “销毁” 了。后面的代码都是错的。
ElevenQAQ 初学 2024-8-6 11:15:28
@Donaldo 哥们儿的解释简洁清晰
a554340466 小成 2024-8-6 11:04:12
读一下 C++17 The complete guide 的 optional 那一章
araraloren 小成 2024-8-6 10:54:09
Very cool feature, thanks for share this.
sanbuks 小成 2024-8-6 10:34:39
@rabbbit 没有必要,直接复制
MoYi123 小成 2024-8-6 10:18:04
编译有警告
main.cpp:43:46: warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
    const ReducedGroupId& reduced_group_id = memo.GetReduceGroupId(group_id).value();

运行有 asan
==7760==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00016ba93320 at pc 0x00010436df8c bp 0x00016ba93250 sp 0x00016ba93248
READ of size 8 at 0x00016ba93320 thread T0
    #0 0x10436df88 in main+0x610 (a.out:arm64+0x100001f88)
    #1 0x187dbe0dc  (<unknown module>)

Address 0x00016ba93320 is located in stack of thread T0 at offset 192 in frame
    #0 0x10436d984 in main+0xc (a.out:arm64+0x100001984)

  This frame has 7 object(s):
    [32, 40) 'ref.tmp.i.i124'
    [64, 72) 'ref.tmp.i.i103'
    [96, 104) 'ref.tmp.i.i'
    [128, 152) 'tmp'
    [192, 208) 'ref.tmp' <== Memory access at offset 192 is inside this variable
    [224, 232) 'ref.tmp15'
    [256, 264) 'ref.tmp28'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope (a.out:arm64+0x100001f88) in main+0x610
fighterhit 小成 2024-8-6 09:56:07
人生苦短,学点别的吧
rabbbit 小成 2024-8-6 09:46:46
visual studio 输出的都是 1
这么写行吗?
const ReducedGroupId&& reduced_group_id = std::move(memo.GetReduceGroupId(group_id).value());
InkStone 小成 2024-8-6 09:38:41
试了一下编译时候有 warning 的……都不用开-Wall

test.cpp:21:46: warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
    const ReducedGroupId& reduced_group_id = memo.GetReduceGroupId(group_id).value();
                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

写 C++的时候-Wall -Werror 是个好习惯
12下一页
返回顶部