C++的一个特性是能够创建未命名(匿名)命名空间,如下所示:
namespace {
int cannotAccessOutsideThisFile() { ... }
} // namespace
Run Code Online (Sandbox Code Playgroud)
您会认为这样的功能是无用的 - 因为您无法指定命名空间的名称,所以无法从外部访问其中的任何内容.但是这些未命名的命名空间可以在它们创建的文件中访问,就好像你有一个隐含的using子句.
我的问题是,为什么或何时使用静态函数会更好?或者他们基本上是两种做同样事情的方式?
特别是在C++中,例如:语义差异是什么:
static const int x = 0 ;
Run Code Online (Sandbox Code Playgroud)
和
const int x = 0 ;
Run Code Online (Sandbox Code Playgroud)
两者static
作为键和存储类说明(即内部和功能外).
关于包括警卫的两个常见问题:
第一个问题:
为什么不包括保护我的头文件不受相互的,递归包含的警卫?我不断收到有关不存在的符号的错误,这些符号显然存在,甚至每次我写下类似的东西时都会出现更奇怪的语法错误:
"啊"
#ifndef A_H
#define A_H
#include "b.h"
...
#endif // A_H
Run Code Online (Sandbox Code Playgroud)
"BH"
#ifndef B_H
#define B_H
#include "a.h"
...
#endif // B_H
Run Code Online (Sandbox Code Playgroud)
"的main.cpp"
#include "a.h"
int main()
{
...
}
Run Code Online (Sandbox Code Playgroud)
为什么我会收到编译"main.cpp"的错误?我需要做些什么来解决我的问题?
第二个问题:
为什么不包括防止多个定义的警卫?例如,当我的项目包含两个包含相同标题的文件时,链接器有时会抱怨多次定义某个符号.例如:
"header.h"
#ifndef HEADER_H
#define HEADER_H
int f()
{
return 0;
}
#endif // HEADER_H
Run Code Online (Sandbox Code Playgroud)
"source1.cpp"
#include "header.h"
...
Run Code Online (Sandbox Code Playgroud)
"source2.cpp"
#include "header.h"
...
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我需要做些什么来解决我的问题?
如果我有一个如下所示的C文件,i
和之间有什么区别j
?
#include <stdio.h>
#include <stdlib.h>
static int i;
int j;
int main ()
{
//Some implementation
}
Run Code Online (Sandbox Code Playgroud) 在Makefile中,这可以通过以下方式完成:
g++ -DGIT_SHA1="`git log -1 | head -n 1`" ...
Run Code Online (Sandbox Code Playgroud)
这非常有用,因为二进制文件知道确切的提交SHA1,所以它可以在segfault的情况下转储它.
我如何用CMake实现同样的目标?
链接器报告重复的符号:
#ifndef testttt
#define testttt
void anything(){
std::cout<<"hellooooooo";
}
#endif
Run Code Online (Sandbox Code Playgroud)
因为它在包含防护内部,所以我希望这个函数只定义一次.但显然不是.
我知道我可以把static
它放在它前面然后它会工作(我仍然觉得具有讽刺意味,因为静态应该给它内部链接,但该函数可以从多个cpp文件中使用).
所以我想我的两部分问题是:1)为什么包含警戒不会阻止此功能的多个定义,就像它们对其他标题项一样,2)为什么这个static
词在静态应该阻止名称可见时解决这个问题在其他翻译单位?我添加它,我实际上可以从包含此头文件的任何地方调用此函数.
C++中的static
全局和非static
全局标识符有什么区别?
我想知道volatile关键字与register,const和static关键字的不同用途.我不确定有什么影响,所以我想:
register volatile int T=10;
Run Code Online (Sandbox Code Playgroud)
建议编译器将T存储在寄存器中,并且可以从外部某处修改T的值(OS,硬件,另一个线程)
const volatile int T=10;
Run Code Online (Sandbox Code Playgroud)
程序本身不能修改T,但T可以在代码之外的某处修改.
static volatile int T=10;
Run Code Online (Sandbox Code Playgroud)
如果T是类的数据成员,则意味着类的所有对象具有相同的T值,并且可以从外部的某处修改T.如果T是文件中的全局变量,则其他文件(属于项目的一部分)中的源代码无法访问T,但可以从外部的某个位置访问T. 如果T是函数中的局部变量,一旦它被初始化,它将保留在内存中直到程序结束,并且可以从外部的某个地方进行修改.
我的想法是否正确,任何有经验的C++开发人员都可以提供一个示例,其中上述内容可能在实际应用程序中使用,或者它是非常罕见的?
这是一些编译和工作正常的C++示例代码:
class A
{
public:
A() {/* empty */}
private:
friend void IncrementValue(A &);
int value;
};
void IncrementValue(A & a)
{
a.value++;
}
int main(int, char **)
{
A a;
IncrementValue(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,我想要做的是将IncrementValue()声明为static,这样就无法从另一个编译单元看到或调用它:
static void IncrementValue(A & a)
{
a.value++;
}
Run Code Online (Sandbox Code Playgroud)
但是,这样做会给我一个编译错误:
temp.cpp: In function ‘void IncrementValue(A&)’:
temp.cpp:12: error: ‘void IncrementValue(A&)’ was declared ‘extern’ and later ‘static’
temp.cpp:8: error: previous declaration of ‘void IncrementValue(A&)’
Run Code Online (Sandbox Code Playgroud)
...并且更改要匹配的朋友声明无济于事:
friend static void IncrementValue(A &);
Run Code Online (Sandbox Code Playgroud)
...因为它给出了这个错误:
temp.cpp:8: error: storage class specifiers invalid …
Run Code Online (Sandbox Code Playgroud) c++ ×7
static ×4
c ×1
c++-faq ×1
cmake ×1
const ×1
friend ×1
git ×1
global ×1
header-files ×1
identifier ×1
java ×1
namespaces ×1
sha1 ×1
tdd ×1
unit-testing ×1
volatile ×1