C++中弱符号(弱引用)的意义及实例

今天读别人代码时看到一个“#pragma weak”,一时没明白,上网研究了一个下午终于稍微了解了一点C、C++中的“弱符号”,下面是我的理解,不正确的地方望大家指正。

本文主要从下面三个方面讲“弱符号”:

1. 什么是“弱符号”? 它与“强符号”的区别是什么?

2. 弱符号的有什么作用?

3. 弱符号的实际应用实例

1.什么是弱符号?

在WikiPedia中弱符号的定义是:

a weak symbol is a symbol definition in an object file or dynamic library that may be overridden by other symbol definitions

  

A weak symbol denotes a specially annotated symbol during linking of Executable and Linkable Format (ELF) object files. By default, without any annotation, a symbol in an object file is strong. During linking, a strong symbol can override a weak symbol of the same name. In contrast, two strong symbols that share a name yield a link error during link-time. When linking a binary executable, a weakly declared symbol does not need a definition. In comparison, (by default) a declared strong symbol without a definition triggers an undefined symbol link error.
Weak symbols are not mentioned by C or C++ language standards; as such, inserting them into code is not very portable. Even if two platforms support the same or similar syntax for marking symbols as weak, the semantics may differ in subtle points, e.g. whether weak symbols during dynamic linking at runtime lose their semantics or not

从第一个定义可以知道,“弱符号“是在一个文件或者动态库中定义的,可以被其他地方定义的符号overridden的符号。这里重点是“overridden”

从第二个定义,我们可以知道“弱符号”跟强符号主要有如下区别:

1. 弱符号可以只有申明,没有定义,强符号必须有定义

2. 弱符号可以定义多次,强符号只能定义。

另外第二个定义中还提到,弱符号并不是C、C++规范中的内容,这个跟编译器相关,不可移植。

在中文的很多文章中把weak symbol分为了两种“弱符号”(变量)“弱引用”(函数),但WikiPedia中弱符号的例子都是用的函数。

2.弱符号的作用

我的理解“弱符号变量“是C中遗留下来的,它除了引起麻烦,没有什么作用。C语言中凡是没有初始化的全局变量都是弱符号变量,如果存在多个同名的弱符号变量,编译器在链接时可以任意选一个(有的编译器选择占用空间最大的那个定义)。这样,你的代码中定义了一个x,忘了初始化,而你用到的某个库中又刚好定义了一个未初始化的x,后果大家可以自己想。C++中不会出现这个问题,因为C++中所有未初始化的全局变量都初始化为0。

弱符号函数的主要作用是为了多态,即使用定义中的”overridden“,一般在库中使用得比较多,比如你在你的库中为某个函数提供一个默认实现,用户如果想定制化的话可以自己实现一个。

例子:在library_foo.h中什么函数foo为弱符号函数,library_foo.cc中为foo提供一个默认实现,在my_foo.cc中为foo提供一个定制化的实现。

注:定义一个函数为弱函数有两种方式

1. 使用“#pragma week function”

2. 函数后面加“ __attribute__((weak))”,

我用的gcc好像不支持第一种方式。

//library_foo.h

#ifndef __LIBRARY_FOO_H__
#define __LIBRARY_FOO_H__

void foo() __attribute__((weak));
void f();   

#endif
//library_foo.cc

#include <iostream>
#include "library_foo.h"

void foo(){
    std::cout<<"default foo"<<std::endl;
}

void f(){
    foo();
}
//main.cc

#include <iostream>
#include "library_foo.h"

using namespace std;

int main(int argc, char* argv[]){
   f();
}
//my_foo.cc

#include <iostream>

void foo(){
    std::cout<<"My customized foo"<<std::endl;
}

编译及运行结果如下:

> g++ library_foo.cc main.cc my_foo.cc -o customized.x
> g++ library_foo.cc main.cc -o not_customized.x
> ./customized.x
my customized foo
> ./not_customized.x
default foo

可以看到,当链接my_foo.cc是,使用的是定制的foo.

3. 弱符号的实际应用实例

在C++库中,如下函数都是弱符号函数

void *operator new(std::size_t);
void *operator new(std::size_t, std::nothrow_t const &) noexcept;
void *operator new[](std::size_t);
void *operator new[](std::size_t, const std::nothrow_t&) noexcept;
void operator delete(void *) noexcept;
void operator delete(void *, std::nothrow_t const &) noexcept;
void operator delete[](void *) noexcept;
void operator delete[](void *, std::nothrow_t const &) noexcept;
时间: 2024-10-11 22:19:57

C++中弱符号(弱引用)的意义及实例的相关文章

嵌入式C语言自我修养 09:链接过程中的强符号和弱符号

9.1 属性声明:weak GNU C 通过 attribute 声明weak属性,可以将一个强符号转换为弱符号. 使用方法如下. void __attribute__((weak)) func(void); int num __attribte__((weak); 编译器在编译源程序时,无论你是变量名.函数名,在它眼里,都是一个符号而已,用来表征一个地址.编译器会将这些符号集中,存放到一个叫符号表的 section 中. 在一个软件工程项目中,可能有多个源文件,由不同工程师开发.有时候可能会遇

关于C语言中的强符号、弱符号、强引用和弱引用的一些陋见,欢迎指正

首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引用.在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样感觉的朋友交流也希望高人指点. 首先我们看一下书中关于它们的定义. 引入场景:(1)文件A中定义并初始化变量i(int i = 1), 文件B中定义并初始化变量i(int i = 2).编译链接A.B时会报错b.o:(.data+0x0): multiple definition of `i':a.o:(.d

浅谈C语言中的强符号、弱符号、强引用和弱引用

摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014-10-31 我要评论 这篇文章主要介绍了C语言中的强符号.弱符号.强引用和弱引用的定义及相关内容,非常的简单易懂,有需要的朋友可以参考下 首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引用.在看到3.5.5节弱符号和强符号时,我感觉有些困惑

C语言中的强符号与弱符号

注意,强符号和弱符号都是针对定义来说的,不是针对符号的引用. 一.概述 在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初始化的全局变量是弱符号. 对于它们,下列三条规则使用: ① 同名的强符号只能有一个,否则编译器报"重复定义"错误. ② 允许一个强符号和多个弱符号,但定义会选择强符号的. ③ 当有多个弱符号相同时,链接器选择占用内存空间最大的那个. 二.哪些符号是弱符号? 我们经常在编程中碰到一种情况叫符号重复定义.多个目标文件中含有相同名字全局符号的定义,那么

GCC中的弱符号与强符号

我们经常在编程中碰到一种情况叫符号重复定义.多个目标文件中含有相同名字全局符号的定义,那么这些目标文件链接的时候将会出现符号重复定义的错误.比如我们在目标文件A和目标文件B都定义了一个全局整形变量global,并将它们都初始化,那么链接器将A和B进行链接时会报错: [html] view plain copy 1 b.o:(.data+0x0): multiple definition of `global' 2 a.o:(.data+0x0): first defined here 这种符号的

弱符号与强符号,弱引用与强引用

1.弱符号与强符号 对C/C++而言,编译器默认函数和初始化了的全局变量为强符号.未初始化的全局变量为弱符号.此处弱符号与强符号均是针对定义来说的,不是针对符号的引用.也可以通过GCC的 "__attribute__((weak))"来定义任何一个强符号为弱符号. [cpp] view plain copy extern in ext; int weak; int strong = 1; __attribute__((weak)) int weak2 = 1; int main() {

java中四种引用类型(对象的强、软、弱和虚引用)

对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出O

Java中强、软、弱、虚引用

一.前言 忘记之前是怎么接触到Java的强.软.弱.虚引用的了,恍恍惚惚好像是在看垃圾回收的时候,略过了这些个概念~这些知识在平时开发中使用的真是少之又少(也许我的level还不够)~今天就将这些整理完毕吧~ 二.正文 对于Java中这几种引用的理解,有助于理解JVM的回收内存的机制.先说下在JVM执行垃圾回收时,如何处理它们所引用的对象: 1)强引用,任何时候都不会被垃圾回收器回收,如果内存不足,宁愿抛出OutOfMemoryError. 2)软引用,只有在内存将满的时候才会被垃圾回收器回收,

Java中的四种引用(强引用、软引用、弱引用、虚引用)

以下内容摘自<深入理解Java虚拟机 JVM高级特性与最佳实践>第2版,强烈推荐没有看过的同学阅读,读完的感觉就是"原来学的都是些什么瘠薄东西(╯‵□′)╯︵┴─┴" 在JDK1.2以前,Java中的引用的定义很传统:如果 reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用.这种定义很纯粹,但是太过狭隘,一个对象在这种定义下只有被引用或者没有被引用两种状态,对于如何描述一些"食之无味,弃之可惜"的对象就显得