我发现了一个具有以下语法的C ++代码:
void MyClass::method()
{
beginResetModel();
{
// Various stuff
}
endResetModel();
}
我不知道为什么在以{ }
结尾的行之后有;
但似乎没有问题让它编译并运行。是否有可能这与代码可能是异步的事实有关(我还不确定)?或许{ }
只是在这里划分代码的一部分,并没有真正有所作为,但说实话,我对此表示怀疑。我不知道,有人知道这个语法是什么意思吗?
更多信息:整个项目中没有其他对beginResetModel
,resetModel
或ResetModel
的引用(使用grep搜索)。顺便说一下这个项目是Qt之一。也许它是我无法听到的另一个与Qt相关的宏。
答案 0 :(得分:8)
使用{}
会创建new scope。在您的情况下,在这些大括号中创建的任何变量最终都将不再存在于}
。
答案 1 :(得分:4)
beginResetModel(); { // Various stuff } endResetModel()
代码中的开括号和闭括号是C ++中非常的重要功能,因为它们分隔了一个新的范围。您可以将此功能与其他强大的语言功能结合使用: destructors 。
因此,假设在这些大括号内你有代码可以创建各种对象,比如图形模型或其他什么。
假设这些对象是分配资源的类的实例(例如视频卡上的纹理),并且这些类具有释放已分配资源的析构函数,则可以保证在{{ 1}},这些析构函数是自动调用的。
以这种方式,在结束大括号之外的代码之前,所有分配的资源都自动释放。在您的样本中调用}
之前。
此自动和确定性资源管理是C ++的一项重要功能。
现在,假设您删除了花括号,并且您的方法如下所示:
endResetModel()
现在,代码的void MyClass::method()
{
beginResetModel();
// {
// Various stuff
// }
endResetModel();
}
部分中创建的所有对象都将在终止Various stuff
的{{1}}之前被销毁,但之后对}
的调用。
因此,在这种情况下,您最终会进行MyClass::method()
调用,然后是之后运行的其他发布代码。这可能会导致错误。
另一方面,定义endResetModel()
中包含的新范围的花括号确保所有在此范围内创建的对象在 {{1>之前被销毁调用。
答案 2 :(得分:0)
{}
分隔范围。这意味着在其中声明的任何变量都无法在其外部访问,并在达到}
后从内存中删除。这是一个例子:
#include <iostream>
using namespace std;
class MyClass{
public:
~MyClass(){
cout << "Destructor called" << endl;
}
};
int main(){
{
int x = 3;
MyClass foo;
cout << x << endl; //Prints 3
} //Here "Destructor called" is printed since foo is cleared from the memory
cout << x << endl; //Compiler error, x isn't defined here
return 0;
}
通常,范围用于函数,循环,if语句等,但您完全可以使用范围而不需要任何语句。这对于在switch
中声明变量特别有用(this answer解释了原因)。
答案 3 :(得分:0)
正如其他人所指出的那样,花括号创造了一个新的范围,但也许有趣的是为什么你想要那样做 - 也就是说,使用它之间的区别是什么使用它。在某些情况下,范围显然是必要的,例如使用if
或for
块;如果你不在他们之后创建一个范围,你只能有一个陈述。另一个可能的原因是,你可能在函数的一个部分中使用了一个变量而没有在该部分之外使用它,所以你将它放在自己的范围内。但是,范围失控语句的主要用途与RAII有关。声明实例变量(不是指针或引用)时,它始终被初始化;当它超出范围时,它总是被销毁。这可用于定义需要在开始时进行一些设置的块以及在末尾需要进行一些拆卸的块(如果您熟悉Python,则类似于with
块)。
举个例子:
#include <mutex>
void fun(std::mutex & mutex) {
// 1. Perform some computations...
{
std::lock_guard<std::mutex> lock(mutex);
// 2. Operations in this scope are performed with the mutex locked
}
// 3. More computations...
}
在此示例中,第2部分仅在获取互斥锁后运行,并在第3部分启动之前释放。如果删除其他范围:
#include <mutex>
void fun(std::mutex & mutex) {
// 1. Perform some computations...
std::lock_guard<std::mutex> lock(mutex);
// 2. Operations in this scope are performed with the mutex locked
// 3. More computations...
}
在这种情况下,在开始第2部分之前获取互斥锁,但它一直保持到第3部分完成(可能在线程之间产生比必要更多的互锁)。但请注意,在这两种情况下都无需指定何时释放锁定; std::lock_guard
负责 获取构造锁定并在销毁时释放它(即当它超出范围时)。