[英]C++ syntax I don't understand
我发现了一个具有以下语法的C ++代码:
void MyClass::method()
{
beginResetModel();
{
// Various stuff
}
endResetModel();
}
我不知道为什么在一行结尾后有{ }
;
但似乎编译和运行没有问题。 是否有可能这与代码可能是异步的事实有关(我还不确定)? 或许{ }
只是在这里划分代码的一部分并没有真正有所作为但老实说我怀疑这一点。 我不知道,有人知道这个语法是什么意思吗?
更多信息:整个项目中没有其他对beginResetModel
, resetModel
或ResetModel
引用(使用grep搜索)。 顺便说一下这个项目是Qt之一。 也许这是我没有听说过的另一个与Qt相关的宏。
使用{}
将创建一个新范围 。 在您的情况下,在这些大括号中创建的任何变量最终都将不再存在于}
中。
beginResetModel(); { // Various stuff } endResetModel()
代码中的开括号和闭括号是C ++中非常重要的特性,因为它们分隔了一个新的范围 。 您可以通过另一种强大的语言功能来理解它的强大功能: 析构函数 。
因此,假设在这些大括号内你有代码创建各种对象,如图形模型,或其他什么。
假设这些对象是分配资源的类的实例(例如视频卡上的纹理),并且这些类具有释放已分配资源的析构函数 ,则可以保证在}
处自动调用这些析构函数。
这样,所有分配的资源都会自动释放,在结束大括号之外的代码之前,例如在样本中调用endResetModel()
之前。
这种自动和确定性的资源管理是C ++的一个关键强大功能。
现在,假设您删除了花括号,并且您的方法如下所示:
void MyClass::method()
{
beginResetModel();
// {
// Various stuff
// }
endResetModel();
}
现在,在终止MyClass::method()
的}
之前 ,但在调用endResetModel()
之后 ,将销毁在 Various stuff
代码段中创建的所有对象。
所以,在这种情况下,你最终的endResetModel()
调用,其次是后运行其他版本的代码。 这可能会导致错误。 另一方面,定义begin/endResetModel()
包含的新作用域的花括号确保在调用endResetModel()
之前销毁在此作用域内创建的所有对象。
{}
分隔范围。 这意味着在其中声明的任何变量都无法在其外部访问,并且一旦到达}
就会从内存中删除。 这是一个例子:
#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
内声明变量特别有用( 这个答案解释了原因)。
正如其他人所指出的那样,花括号创建了一个新的范围,但也许有趣的是你为什么要这样做 - 也就是说,使用它和不使用它之间有什么区别。 存在其中范围是明显需要的情况下,如与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
同时负责获取关于建设锁和(当它超出范围即)释放它上破坏。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.