在函数中使用裸括号是一种好的做法吗?
Is it a good practice to use naked brackets inside functions?
从技术上讲,在C++中,我们可以使用大括号来声明新的作用域。例如,在此函数中,交换两个数字
void swap_int(int& first, int& second)
{
int temp = first;
first = second;
second = temp;
}
我们还可以在它自己的块中声明temp
:
void swap_int(int& first, int& second)
{
// Do stuf...
{
int temp = first;
first = second;
second = temp;
}
// Do other stuff...
}
这显然具有一个优点,即不再需要temp
时会直接删除它。
但是,在我编写的代码中,我从不使用它。此外,在来自第三方库的代码中,我几乎从未见过它。
为什么不公开使用?它是否带来了任何性能提升,或者它只是意味着额外的打字工作?
我认为裸括号本身没有任何问题。它们是语言的一部分,并且定义明确。从历史上看,我发现它们有用的一个地方是使用使用状态代码而不是异常的代码,同时保持常量的优点:
const StatusCode statusCode = DoThing();
if (statusCode == STATUS_SUCCESS)
Foo();
else
Bar();
const StatusCode statusCode2 = DoAnotherThing(); // Eww variable name.
...
另一种选择是:
{
const StatusCode statusCode = DoThing();
if (statusCode == STATUS_SUCCESS)
Foo();
else
Bar();
}
{
// Same variable name, used for same purpose, easy to
// find/replace, and has const guarantees. Great success.
const StatusCode statusCode = DoAnotherThing();
...
}
这同样适用于使用 RAII 的线程锁等对象(互斥对象、信号量等),或者通常您希望生存期极短的任何类型的资源(例如文件句柄)。
就个人而言,我认为它很少见的原因是它可以指示代码气味(尽管并非总是如此)。如果存在裸括号,则可能有机会分解出函数。
举个例子,如果swap_int
有多个作业,那么该函数正在做不止一件事。通过将实际的交换代码提取到另一个函数中,您可以鼓励重用!例如:
template <typename T>
void swap_anything(T &first, T& second)
{
T temp = first;
first = second;
second = temp;
}
// -------------------------------------------
void swap_int(int& first, int& second)
{
// Do stuff...
swap_anything(first, second);
// Do other stuff...
}
有时这是很好的做法(虽然我不喜欢这个词,因为它是主观的和特定于上下文的),但就像生活中的许多事情一样,把它极端化(在光谱的两端)是一个坏主意。
您会看到有时在 RAII 很重要的C++中引入新的作用域,例如在处理线程锁时。有时,创建和销毁对象的确切时刻非常重要,需要控制。在这些情况下,引入新作用域是实现此目的的一种非常有用且经常使用的方法。
但这种情况并不常见。我们(广泛的编程社区)使用的大多数对象都没有需要如此仔细管理的严格生存期。因此,不值得随意引入新的作用域来管理其生存期不值得微观管理的对象的生存期。
如果这样做,就会降低信噪比,人们将很难分辨引入哪些示波器来仔细控制重要资源,哪些示波器不是。这使得在跨团队重构或开发代码时很容易引入错误。至少,你会让编程变得更加乏味,这很糟糕,如果可以的话,你通常应该避免这样做,否则暴力精神病患者可能会把它发泄在你身上。
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- C++ STD 函数运算符:有没有一种方法可以通过函数将一个向量映射到另一个向量上?
- 如果 C 函数仍然可以间接执行(通过回调函数),那么将它声明为静态函数是否是一种不好的做法?
- 构造函数是否有一种现代C++方法来了解其'container'类?
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 有没有一种简单的方法来调用带有默认参数的函数?
- 有没有一种方法可以从函数中返回一个新对象或对现有对象的引用
- 在C++中,有没有一种方法可以让我在不传递参数的情况下拥有一个函数
- 有没有一种方法可以在linux中扫描已构建的ARM库中的函数
- 有没有一种方法可以获得传递给函数的数组的大小
- 常量静态成员函数:有另一种方法可用吗?
- C++11 中的随机数:有没有一种简单的方法可以将生成器种子放在代码的一个位置,然后在不同的函数中使用它?
- 是否有一种方法可以调用一个函数,而不会创建变量,而不会创建变量
- 有没有一种单行方法来调用集合上的 lambda 函数
- 是否有一种非间接、非黑客的方式来保证 constexpr 函数仅在编译时可调用?
- 是否有一种方法可以在超载运算符函数中接触默认运算符函数
- 是否有一种方法可以避免标头文件中使用的constexpr函数输入全局范围,而无需额外的名称空间
- 是否可以将一种函数类型转换为另一种采用相同参数但返回类型不同的函数类型
- 是c++模板元编程的一种函数编程形式