gpt4 book ai didi

c++ - 为什么可以从外部通过指针或引用访问静态本地对象?

转载 作者:可可西里 更新时间:2023-11-01 17:57:21 26 4
gpt4 key购买 nike

您可能知道,局部静态变量不能通过名称在函数外部访问,但可以通过指针或引用访问。所以下面的代码是格式良好的。

但是为什么?我知道这个事实是事实,但没有根据。其实我想要的是C++标准的相关摘录。我正在阅读它,但最终没有找到证据。谁能给我摘录或提示以找到它(因为仅在文档中搜索“静态”会导致超过一百次点击)?

#include <iostream>
using namespace std;

class Test {

public:

int * f(int i) const {
static int j;
j += i;
cout << "now j = " << j << "\n";
return &j;
}

int & g(int i) const { //same as above but handle reference
static int k;
k += i;
cout << "now k = " << k << "\n";
return k;
}

};

int main() {

Test t;

int *p = t.f(3); //=> "now j = 3"
*p += 10;
t.f(0); //=> "now j = 13"

int &r = t.g(3); //=> "now k = 3"
r += 10;
t.g(0); //=> "now k = 13"

}

我查看了 stack overflow 提出的大约 20 个问题,但还没有答案。 (只有一个相关问题:Can I access static variables inside a function from outside。)


对于 future 的读者(或者只是我的笔记):

comment 中所示,这同样适用于类成员的情况,即使它是遥远的和 private

#include <iostream>
using namespace std;

class Base {
private:
int i = 0;
public:
int * return_pointer() { return &i; }
void print() { cout << "i = " << i << "\n"; }
};

class Derived : public Base {
public:
int * return_pointer() { return Base::return_pointer(); }
};

int main() {

Derived d;
d.print(); //=> "i = 0"

int *p = d.return_pointer();
*p = 300;
d.print(); //=> "i = 300"

}

最佳答案

C++17标准(n4659)的相关引述告诉我们关于static变量的存储持续时间:

6.7.1 Static storage duration [basic.stc.static]
1 All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static storage duration. The storage for these entities shall last for the duration of the program (6.6.2, 6.6.4).
...
3 The keyword static can be used to declare a local variable with static storage duration. [ Note: 9.7 describes the initialization of local static variables; 6.6.4 describes the destruction of local static variables. —end note ]

static 函数局部变量的生命周期从程序流第一次遇到声明时开始,到程序终止时结束。

如评论中所述,没有直接引述表示可以通过指针或引用访问此类变量。

然而,以下来自 [basic.life] 的引述(虽然不直接适用于您的场景)讲述了一些关于使用指向其存储仍然有效(已分配)的对象的指针但未发布或重用)但其生命周期尚未开始或已经结束:

6 Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see 15.7. Otherwise, such a pointer refers to allocated storage, and using the pointer as if the pointer were of type void*, is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The program has undefined behavior if:
(6.1) — the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression,
(6.2) — the pointer is used to access a non-static data member or call a non-static member function of the object, or
(6.3) — the pointer is implicitly converted to a pointer to a virtual base class, or
(6.4) — the pointer is used as the operand of a static_cast, except when the conversion is to pointer to cv void, or to pointer to cv void and subsequently to pointer to cv char, cv unsigned char, or cv std::byte, or
(6.5) — the pointer is used as the operand of a dynamic_cast.

关于c++ - 为什么可以从外部通过指针或引用访问静态本地对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55213960/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com