左边的大括号在变量声明中的含义是什么,例如在 T {x} = y 中?

51
这个GitHub文件中的代码使用了一种我不熟悉的C++变量"声明"语法。
std::unique_ptr<CRecentFileList> {m_pRecentFileList} = std::make_unique<CRecentFileList>(...

(m_pRecentFileList在一个超类中声明。)

当你用大括号包裹一个变量声明时,这意味着什么?(不是初始化列表)


我提取了一个最小的测试案例,可以编译。
class foo {
    int* p;
    void f(){
        std::unique_ptr<int> {p} = std::make_unique<int>(1);
    }
};

int* p 改为 std::unique_ptr<int> p 会导致编译错误,原因是 unique_ptr(const unique_ptr&) = delete; 这让我想到花括号声明会将同名的外部作用域变量赋值。我尝试创建了一个测试程序,但它无法编译通过。
int main(){
    int x;
    int {x} = 1;
}

错误:将临时变量用作左值[-fpermissive]

2
这仍然是一个初始化列表,没有变量被声明,而是创建了一个临时对象并调用了移动赋值运算符。这段代码似乎相当无意义。 - user7860670
7
顺便说一句,MCVE使用int {x} = 1;尝试得不错。加1。 - Jarod42
2
我以前从未在这么短的时间内得到过这么多的赞和回复... 我会在明天点赞或接受答案。 - nyanpasu64
巧合的是,您在与类似的问题的同一天提出了这个问题。 - Toby Speight
1个回答

47
这不是一个声明,而是对临时对象的赋值。
std::unique_ptr<int> {p} = std::make_unique<int>(1); 中,std::unique_ptr<int> {p} 创建了一个 unique_ptr 临时对象,它接管了指针 p 指向的对象,然后 std::make_unique<int>(1) 被赋值给了这个临时对象。这导致指针 p 指向的对象被删除,并使得临时对象接管了 make_unique 创建的 int 对象;最后,在 ; 处,临时对象本身被销毁,从而删除了由 make_unique 创建的 int 对象。
最终的结果是 delete p 加上一个无用的 new/delete 周期。
(如果使用圆括号而不是大括号,则会成为一个声明:std::unique_ptr<int> (p) = std::make_unique<int>(1); 等价于 std::unique_ptr<int> p = std::make_unique<int>(1);。)

12
它用于什么? - VLL
7
@Ville-Valtteri:Obfuscating delete m_pRecentFileList :-/(并且还有一个无用的分配)。 - Jarod42
14
我想我找到了这个函数失效的原因。原始开发者认为自己找到了一种聪明(他经常这样做)构建新对象的方式。实际上,对象/指针在构造后立即被删除,导致应用程序在调用该函数后崩溃(因为指针被重置为0xCCCCCCCC)。 - nyanpasu64
@jimbo1qaz 原始指针(m_pRecentFileList)甚至没有更新为指向临时对象,但无论如何,这确实是具有未定义行为的“聪明”代码。 - Arne Vogel
1
所以看了一下之前的问题,这个“可能”不应该被允许,但是因为没有人费心去证明限制默认值以防止这种情况是完全安全的想法,所以它还是被允许的。 - Alex Celeste
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接