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. TinyFrame升级之五:全局缓存的设计及实现

    在任何框架中,缓存都是不可或缺的一部分,本框架亦然.在这个框架中,我们的缓存分为两部分:内存缓存和单次请求缓存.简单说来,就是一个使用微软提供的MemoryCache做扩展,并提供全局唯一实例:另一个 ...

  2. 扩展欧几里得算法(extgcd)

    相信大家对欧几里得算法,即辗转相除法不陌生吧. 代码如下: int gcd(int a, int b){ return !b ? gcd(b, a % b) : a; } 而扩展欧几里得算法,顾名思义 ...

  3. RSA签名验签学习笔记

    RSA私钥签名时要基于某个HASH算法,比如MD5或者SHA1等.之前我一直认为签名的过程是:先对明文做HASH计算,然后用私钥直接对HASH值加密.最近才发现不是那么简单,需要对HASH后的数据进行 ...

  4. 使用 data-* 属性来嵌入自定义数据

    1. HTML 实例 <ul> <li data-animal-type="bird">Owl</li> <li data-animal- ...

  5. Bootstrap系列 -- 1. 如何使用Bootstrap

    一. Bootstrap 简介 Bootstrap 是一个前端框架,使用Bootstrap可以做出很多漂亮的页面,中文官网:http://www.bootcss.com/ 二. Bootstrap核心 ...

  6. js如何判断一个数组

    typeof [] 为一个"object" 不能通过此方法判断一个数组 方法 1.instanceof方法,这个方法用的比较多. 2.这个是es5以后推荐的方法,Object.pr ...

  7. pageEncoding与contentType属性

    1图例分析 由图中可以看出,这个两个属性没有任何关系. 把这两个设置成不同的编码格式对中文显示不会产生任何影响 2.原因分析 pageEncoding规定了以什么编码方式存储和读取,使两者保持一致性, ...

  8. hihocoder1033交错和

    题目链接 坑: 1.ll x,y; z=x*y;可能会溢出,于是我写成x%mod*y%mod 仍旧错误,要写成x%mod*(y%mod). 2.f(9019)=1. 要注意如果为0,下一位的符号根据0 ...

  9. 用自己的话描述wcf中的传输安全与消息安全的区别(三)

    消息交换安全模式 PS:很多书上把transfer security和transport security都翻译成“传输安全”,这样易混淆.我这里把transfer说成消息交换安全. 安全的含义分为验 ...

  10. springMvc发布restFull风格的URL

    package zpark.controller; import org.springframework.stereotype.Controller; import org.springframewo ...