所以我正在查看一些旧的C ++测试书,我发现其中一个问题的解决方案非常酷!我之前从未见过这种“语法”,想问一下是否有人知道它是如何实际运作的,为什么它没有被广泛传授!
问题: 将输出提供给以下代码 - >
int g =10; //TAKE NOTE OF THIS VARIABLE
void func(int &x, int y){
x = x-y;
y = x*10;
cout << x << ',' << y << "\n";
}
void main(int argc, char** argv){
int g = 7; //Another NOTE
func(::g,g); // <----- "::g" is different from "g"
cout << g << ',' << ::g << "\n";
func(g,::g);
cout << g << ',' << ::g << "\n";
}
输出:
3,30
7,3
4,30
4,3
我的问题是“:: :(变量)”语法是如何工作的?它将变量存储在main之外,但存储在哪里(Stack / Heap)?我们可以通过指针改变“全局”变量的值吗?
我认为这可能允许一些非常酷的实现,并希望与像我这样的人分享这些知识:)
答案 0 :(得分:6)
我的问题是“:: :(变量)”语法是如何工作的?
::
是范围解析运算符。使用前面的类或命名空间的名称,这意味着它之后的名称是在该类或命名空间中的范围。在这里,没有任何东西,它意味着它后面的名称是在全局命名空间;也就是说,它在任何类,函数或命名空间之外声明。
通常,您可以在没有::
的情况下按名称引用全局变量。这里需要它,因为全局是由具有相同名称的局部变量隐藏。这是避免全局变量的一个原因:如果添加隐藏它的声明,代码的含义可能会改变。
存储的内存在哪里(堆栈/堆)?
它位于静态存储中,既不在堆栈上也不在堆中。程序开始时分配存储,并持续到程序结束。
如果变量具有复杂类型,则可能在程序启动后的某个时间才初始化;当您的代码在初始化之前使用它时,您可能会遇到模糊和痛苦的错误。这是避免全局变量的另一个原因。
我们可以通过指针更改“全局”变量的值吗?
是。你的例子就是这样,尽管有一个引用而不是一个指针。它也可以直接改变,例如::g = 42;
,任何时候任何代码都是如此,因此很难推断出包含它们的程序的状态。这是避免全局变量的另一个原因。
我认为这可能允许一些非常酷的实现
由于我在这里和其他人提到的原因,全局变量几乎总是比它们的价值更麻烦。如果我是你,我会避开它们。
答案 1 :(得分:1)
Static variables are in a category of their own:他们不是真的在“堆栈”或“堆”。您的进程的内存空间中有一个特定部分用于保存与堆栈或堆不同的静态变量。请参阅给出的链接以进行全面讨论。
您仍然可以像使用任何其他变量一样使用此变量,并且您确实可以获取指向它的指针并通过指针更改其值。
正如其他人所建议的那样,不要对此感到太兴奋:global variables are frowned upon。它们往往是设计不佳的标志,并且存在许多现实世界的缺点和缺陷。
答案 2 :(得分:1)
::
是范围解析运算符。如果在bar
命名空间中声明了一些foo
标识符,则可以使用foo::bar
来表示它。如果您的作用域解析运算符之前没有任何内容,那么它表示全局名称空间。这就是为什么::g
引用全局命名空间中的g
的原因。
它获取存储在main之外的变量,但存储的内存在哪里(Stack / Heap)?我们可以改变那个&#34; Global&#34;通过指针变量?
我不确定为什么会出现这些问题。如果没有声明本地g
,他们正在使用全局变量g
。 ::
所需的唯一原因是因为有两个g
标识符。你可以用任何其他具有相同类型的对象做任何事情。
答案 3 :(得分:1)
普通g
表示“使用最本地的g
”,::g
表示使用全局g
。
更一般,example::g
表示“使用命名空间示例中的g
”。
另外,如果你可以以某种方式避免它(你通常可以),不要使用全局变量,不要使用这样的技巧,它很容易出错。
答案 4 :(得分:0)
C ++中的::
称为范围解析运算符。它在许多地方都有记录(例如here)。它提供了一种命名变量的方法,这些变量可能与当前代码的范围不同。 ::
(A::g
前面有一个可选的范围规范,例如,对于命名空间A
);没有范围规范表示“全局”范围。您可以使用具有范围解析运算符的变量来完成您可以对变量执行的任何操作(包括通过指针进行修改)。变量生存的位置由其定义的范围定义。
静态变量(全局或非全局)位于以下几个位置之一,具体取决于编译器以及可能的初始化方式。例如,请参阅this thread。
答案 5 :(得分:0)
通过将::
添加到变量或函数中,您告诉编译器它应该在全局命名空间中查找此变量/函数,即在函数范围之外。