简体   繁体   English

C ++语法我不明白

[英]C++ syntax I don't understand

I've found a C++ code that has this syntax: 我发现了一个具有以下语法的C ++代码:

void MyClass::method()
{
    beginResetModel();

    {
        // Various stuff
    }

    endResetModel();
}

I've no idea why there are { } after a line ending with ; 我不知道为什么在一行结尾后有{ } ; but it seems there is no problem to make it compile and run. 但似乎编译和运行没有问题。 Is it possible this as something to do with the fact that the code may be asynchronous (I'm not sure yet)? 是否有可能这与代码可能是异步的事实有关(我还不确定)? Or maybe the { } are only here to delimit a part of the code and don't really make a difference but honestly I doubt this. 或许{ }只是在这里划分代码的一部分并没有真正有所作为但老实说我怀疑这一点。 I don't know, does someone has any clue what this syntax mean ? 我不知道,有人知道这个语法是什么意思吗?

More info: There is no other reference to beginResetModel , resetModel or ResetModel in the whole project (searched with grep). 更多信息:整个项目中没有其他对beginResetModelresetModelResetModel引用(使用grep搜索)。 Btw the project is a Qt one. 顺便说一下这个项目是Qt之一。 Maybe it's another Qt-related macro I haven't heard of. 也许这是我没有听说过的另一个与Qt相关的宏。

Using {} will create a new scope . 使用{}将创建一个新范围 In your case, any variable created in those braces will cease to exist at the } in the end. 在您的情况下,在这些大括号中创建的任何变量最终都将不再存在于}中。

  beginResetModel(); { // Various stuff } endResetModel() 

The open and close braces in your code are a very important feature in C++, as they delimit a new scope . 代码中的开括号和闭括号是C ++中非常重要的特性,因为它们分隔了一个新的范围 You can appreciate the power of this in combination with another powerful language feature: destructors . 您可以通过另一种强大的语言功能来理解它的强大功能: 析构函数

So, suppose that inside those braces you have code that creates various objects, like graphics models, or whatever. 因此,假设在这些大括号内你有代码创建各种对象,如图形模型,或其他什么。

Assuming that these objects are instances of classes that allocate resources (eg textures on the video card), and those classes have destructors that release the allocated resources, you are guaranteed that, at the } , these destructors are automatically invoked. 假设这些对象是分配资源的类的实例(例如视频卡上的纹理),并且这些类具有释放已分配资源的析构函数 ,则可以保证在}自动调用这些析构函数。

In this way, all the allocated resources are automatically released, before the code outside the closing curly brace, eg before the call to endResetModel() in your sample. 这样,所有分配的资源都会自动释放,在结束大括号之外的代码之前,例如在样本中调用endResetModel()之前。

This automatic and deterministic resource management is a key powerful feature of C++. 这种自动确定性的资源管理是C ++的一个关键强大功能。


Now, suppose that you remove the curly braces, and your method looks like this: 现在,假设您删除了花括号,并且您的方法如下所示:

void MyClass::method()
{
    beginResetModel();

    // {
        // Various stuff
    // }

    endResetModel();
}

Now, all the objects created in the Various stuff section of code will be destroyed before the } that terminates the MyClass::method() , but after the call to endResetModel() . 现在,在终止MyClass::method()} 之前 ,但调用endResetModel() 之后 ,将销毁 Various stuff代码段中创建的所有对象。

So, in this case, you end up with the endResetModel() call, followed by other release code that runs after it. 所以,在这种情况下,你最终的endResetModel()调用,其次是运行其他版本的代码。 This may cause bugs. 这可能会导致错误。 On the other hand, the curly braces that define a new scope enclosed in begin/endResetModel() do guarantee that all the objects created inside this scope are destroyed before endResetModel() is invoked. 另一方面,定义begin/endResetModel()包含的新作用域的花括号确保在调用endResetModel() 之前销毁此作用域内创建的所有对象。

{} delimits a scope. {}分隔范围。 That means that any variable declared inside there is not accessible outside of it and is erased from memory once the } is reached. 这意味着在其中声明的任何变量都无法在其外部访问,并且一旦到达}就会从内存中删除。 Here is an example: 这是一个例子:

#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;
}

Usually scopes are used for functions, loops, if-statements, etc, but you're perfectly allowed to use scopes without any statement before them. 通常作用域用于函数,循环,if语句等,但您完全可以使用作用域而不需要任何语句。 This can be particularly useful to declare variables inside a switch ( this answer explains why). 这对于在switch内声明变量特别有用( 这个答案解释了原因)。

As others have pointed out, the curly braces create a new scope, but maybe the interesting thing is why would you want to do that - that is, what is the difference between using it and not using it. 正如其他人所指出的那样,花括号创建了一个新的范围,但也许有趣的是你为什么要这样做 - 也就是说,使用它和不使用它之间有什么区别。 There are cases where scopes are obviously necessary, such as with if or for blocks; 存在其中范围是明显需要的情况下,如与iffor块; if you don't create a scope after them you can only have one statement. 如果你不在它们之后创建一个范围,你只能有一个语句。 Another possible reason is that maybe you use one variable in one part of the function and do not one it to be used outside of that part, so you put it into its own scope. 另一个可能的原因是,你可能在函数的一个部分中使用了一个变量而没有在该部分之外使用它,所以你将它放在自己的范围内。 However, the main use of scopes out of control statements has to do with RAII . 但是,范围失控声明的主要用途与RAII有关 When you declare an instance variable (not a pointer or reference), it is always initialized; 声明实例变量(不是指针或引用)时,它始终被初始化; when it goes out of scope, it is always destroyed. 当它超出范围时,它总是被销毁。 This can be used to define blocks that require some setup at the beginning and some tear down at the end (if you are familiar with Python, similar to with blocks). 这可以用来定义需要的开头有一些设置和一些推倒在结束(如果你熟悉Python,类似于块with块)。

Take this example: 举个例子:

#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...
}

In this example, part 2 is only run after the mutex has been acquired, and is released before part 3 starts. 在此示例中,第2部分仅在获取互斥锁后运行,并在第3部分启动之前释放。 If you remove the additional scope: 如果删除其他范围:

#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...
}

In this case the mutex is acquired before starting part 2, but it is held until part 3 is complete (possibly producing more interlocking between threads than necessary). 在这种情况下,在启动第2部分之前获取互斥锁,但它一直保持到第3部分完成(可能在线程之间产生比必要更多的互锁)。 Note, however, that in both cases there was no need to specify when the lock is released; 但请注意,在这两种情况下都无需指定何时释放锁定; std::lock_guard is responsible for both acquiring the lock on construction and releasing it on destruction (ie when it goes out of scope). std::lock_guard 同时负责获取关于建设锁和(当它超出范围即)释放它上破坏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM