extraction from The C++ Programming Language, 4th. edition, Bjarne Stroustrup

1. If no initializer is specified, a global, namespace, local static, or static member (collectively called static objects) is initialized to {} of the appropriate type.

2. We classify objects based on their lifetimes:

  • Automatic: Unless the programmer specifies otherwise, an object declared in a function is created when its definition is encountered and destroyed when its name goes out of scope. Such objects are sometimes called automatic objects. In a typical implementation, automatic objects are allocated on the stack; each call of the function gets its own stack frame to hold its automatic objects.
  • Static: Objects declared in global or namespace scope and statics declared in functions or classes are created and initialized once (only) and "live" until the program terminates. Such objects are called static objects. A static object has the same address throughout the life of a program execution. Static objects can cause serious problems in a multi-thread program because they are shared among all threads and typically require locking to avoid data races.
  • Free store: Using the new and delete operators, we can create objects whose lifetimes are controlled directly.
  • Temporary objects (e.g., intermediate results in a computation or an object used to hold a value for a reference to const argument): their lifetime is determined by their use. If they are bound to a reference, their lifetime is that of the reference; otherwise, they "live" until the end of the full expression of which they are part. A full expression is an expression that is not part of another expression. Typically, temporary objects are automatic.
  • Thread-local objects; that is, objects declared thread_local: such objects are created when their thread is and destroyed when their thread is.

Static and automatic are traditionally referred to as storage classes.

Array elements and nonstatic class members have their lifetimes determined by the object of which they are part.

3. An array can be allocated statically, on the stack, and on the free store. For example:

    int a1[10];                  // 10 ints in static storage
void f(){
int a2[20];
int *p = new int[40]; // 40 ints on the free store
// ...
}

4. A string literal is statically allocated so that it is safe to return one from a function. For example

    const char* error_message(int i){
// ...
return "range error"
}

5. [10.4.5] (??) The address of a statically allocated object, such as a global variable, is a constant. However, its value is assigned by the liker, rather than the compiler, so the compiler cannot know the value of such an address constant. That limits the range of constant expressions of pointer and reference type. For example:

    constexpr const char *p1="asdf";
constexpr const char *p2=p1; // OK
constexpr const char *p2=p1+2; // error: the compiler does not know the value of p1
constexpr char c=p1[2]; // OK, c=='d'; the compiler knows the value pointed to by p1

6. [11.2.2] (??) To deallocate space allocated by new, delete and delete[] must be able to determine the size of the object allocated. This implies that an object allocated using the standard implementation of new will occupy slightly more space than a static object. At a minimum, space is needed to hold the object's size. Usually two or more words per allocation are used for free-store management. Most modern machines use 8-byte words. This overhead is not significant when we allocate many objects or large objects, but it can matter if we allocate lots of small obejects (e.g., ints) on the free store.

7. A member function may be specified as static, indicating that it is not associated with a particular object.

8. [12.1.8] A name defined in a function is commonly referred to as a local name. A local variable or constant is initialized when a thread of execution reaches its definition. Unless declared static, each invocation of the function has its own copy of the variable. If a local variable is declared static, a single, statically allocated object object will be used to represent that variable in all calls of the function. It will be initialized only the first time a thread of execution reaches its definition (rather than at compile time). For example:

    void f(int a){
while(a--){
static int n=0; //initialized once
int x=0;
cout<<"n == "<<n++<<", x == "<<x++<<'\n';
}
}

A static local variable allows the function to preserve information between calls without introducing a global variable that might be accessed and corrupted by other functions.

Initialization of a static local variable does not lead to a data race unless you enter the function containing it recursively or a deadlock occurs. That is, the C++ implementation must guard the initialization of a local static variable with some kind of lock-free construct (e.g., a call_once;). The effect of initializing a local static recursively is undefined. For example:

    int fn(int n){
static int n1=n; // OK
static int n2=f(n-1)+1; //undefined
return n;
}

A static local variable is useful for avoiding order dependencies among nonlocal variables.

9. A variable defined without an initializer in the global or a namespace scope is initialized by default. This is not the case for non-static local variables or the objects created on the free store.

10. A name that can be used in translation units different from the one in which it was defined was said to have external linkage. A name that can be referred to only in the translation unit in which it is defined is said to have internal linkage. For example:

    static int x1=1;    //internal linkage
const char x2='a'; //internal linkage

When used in namespace scope (including the global scope), the keyword static (somewhat illogically) means "not accessible from other files" (i.e., internal linkage). If you wanted x1 to be accessible from other source files ("have external linkage"), you should remove the static. The key word const implies default internal linkage, so if you wanted x2 to have external linkage, you need to precede its definition with extern:

    int x1=1;    // external linkage
extern const char x2='a'; // external linkatge

Names that a linker does not see, such as the names of local variables, are said to have no linkage.

11. In principle, a variable defined outside any function (that is, global, namespace, and class static variables) is initialized before main() is invoked. Such nonlocal variables in a translation unit are initialized in their definition order. If such variable has no explicit initializer, it is by default initialized to the default for its type.

12. A variable that is part of a class, yet is not part of an object of that class, is called a static member. There is exactly one copy of a static member instead of one copy per object, as for ordinary non-static members. Similarly, a function that needs access to members of a class, yet doesn't need to be invoked for a particular object, is called a static member function.

A static member can be referred to like any other member. In addition, a static member can be referred to without mentioning an object. Instead, ins name is qualified by the name of its class.

if used, a static member--function or data member--must be defined somewhere. The keyword static is not repeated in the definition of a static member.

In multi-threaded code, static data member require some kind of locking or access discipline to avoid race conditions. Since multi-threading is now very common, it is unfortunate that use of static data members was quite popular in older code. Older code tends to use static members in ways that imply race conditions.

13. A static class member is statically allocated rather than part of each object of the class. Generally, the static member declaration acts as a declaration for a definition outside the class. For example:

    class Node{
// ...
static int node_count; // declaration
}; int Node::node_count=0; // definition

However, for a few simple special cases, it is possible to initialize a static member in the class declaration. The static member must be a const of an integral or enumeration type, or a constexpr of a literal type, and the initializer must be a constant-expression. For example:

    class Curious{
public:
static const int c1=7; // OK
static int c2=11; // error: not const
const int c3=13; // OK but not static
static const int c4=sqrt(9); //error: in-class initializer not constant
static const float c5=7.0; //error: in-class not integral (use constexpr rather than const)
// ...
};

If (and only if) you use an initialized member in a way that requires it to be stored as an object in memory, the member must be (uniquely) defined somewhere. The initializer may not be repeated:

    const int Curious::c1;    // don't repeat initializer here
const int *p = &Curious::c1; // OK: Curious::c1 has been defined

Note that const int Curious::c1; is definition of Curious::c1 which is declared in Curious as static const int c1;.

C++ essentials 之 static 关键字的更多相关文章

  1. 浅谈Static关键字

    1.使用static关键字声明的属性为全局属性 未使用static关键字指定city之前,如果需要将Tom,Jack,Mary三人的城市均改成Beijing,需要再次声明三次对象的city为Beiji ...

  2. (转)Java中的static关键字解析

    转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: &q ...

  3. PHP的final关键字、static关键字、const关键字

    在PHP5中新增加了final关键字,它可以加载类或类中方法前.但不能使用final标识成员属性,虽然final有常量的意思,但在php中定义常量是使用define()函数来完成的. final关键字 ...

  4. Java Static关键字详解

    提起static关键字,相信大家绝对不会陌生,但是,想要完全说明白,猛的一想,发现自己好像又说不太明白... ...比方说,昨天被一个同学问起的时候... ... 当然,不是所有人都像我一样学艺不精的 ...

  5. 关于Java中的static关键字

    Java中的 static 关键字,确实是一个关键的字(key word),今天就来总结一下它的用法,说说为什么关键. Java中的 static 关键字主要是用来做内存管理的.理解了这句话才能够比较 ...

  6. Java中的static关键字解析

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  7. c++中static关键字的用法总结

    类中的静态成员真是个让人爱恨交加的特性.我决定好好总结一下静态类成员的知识点,以便自己在以后面试中,在此类问题上不在被动. 静态类成员包括静态数据成员和静态函数成员两部分. 一 静态数据成员: 类体中 ...

  8. static关键字

    static关键字 static是静态修饰符,一般修饰成员.被static修饰的成员属于类,不属于单个这个类的某个对象. 1.static关键字的特点 a:随着类的加载而加载 b:优先于对象存在 (还 ...

  9. C++中的static关键字的总结

    C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 1.面向过程设计中的st ...

随机推荐

  1. 《细细品味Hive》系列课程

    Hi,博友: 我是解耀伟,笔名是虾皮,最近我在极客学院录制Hive系列教程,也是督促自己学习一种方式,可以把自己的学习积累有方向,星期天也能做点有意义的事情.在做每一期的过程中,需要找资料,总结,先自 ...

  2. 移动端页面(css)调试之“weinre大法”

    移动端页面调试一般分两步.第一步我们需要把本地(pc端)写的页面效果展现在移动端,一个很方便的办法是用 fiddler 作为代理,具体可以参考 如何用 fiddler 代理调试本地手机页面,这样我们就 ...

  3. 用Dart&Henson玩转Activity跳转

    用Dart&Henson玩转Activity跳转 Extra是Android标准的组件之间(Activity/Fragment/Service等)传递数据的方式.本文介绍了开源项目Dart的使 ...

  4. Windows Server+AMD GPU+HDMI时_黑边_不铺满问题的解决办法

    HDMI接显示器或电视,有黑边或者被放大了是个很常见的问题,显卡设置界面里改下Scale或者Overscan/Underscan就行,可问题是WindowsServer版的CCC没有控制颜色对比度和缩 ...

  5. 匈牙利算法(codevs2776)

    type node=^link; link=record des:longint; next:node; end; var n,m,i,t,num:longint; p:node; nd:..] of ...

  6. Linux终端更改提示符

    打开~/.bashrc可以看到命令提示的内容为:\u@\h\w\$ \u表示用户名,\h表示主机名,\w表示当前目录,\$表示命令提示符(普通用户$,超级用户#) 这个命令提示符有点长,很碍事,\u@ ...

  7. Ubuntu backlight

    我们可以通过键盘来调节亮度,但是那样亮度无法微调,每次变亮变得太多. 在 /sys/class/backlight/nv_backlight 这个目录下,brightness 是最主要的.backli ...

  8. linux基础-第十二单元 硬盘分区、格式化及文件系统的管理一

    第十二单元 硬盘分区.格式化及文件系统的管理一 硬件设备与文件名的对应关系 硬盘的结构及硬盘分区 为什么进行硬盘分区 硬盘的逻辑结构 Linux系统中硬盘的分区 硬盘分区的分类 分区数量的约束 使用f ...

  9. AndroidStudio修改项目名称

    项目名称修改了,想修改Android Studio 中 project的名字 右键project 的名字,refactor - rename ,填写好新名字后修改,被提示 “can’t rename ...

  10. poj3233 矩阵等比数列求和 二分

    对于数列S(n) = a + a^2 + a^3 +....+ a^n; 可以用二分的思想进行下列的优化. if(n & 1) S(n) = a + a^2 + a^3 + ....... + ...