关于namespace或global作用域内变量和常量以及static修饰符

我们的讨论基于下列准则:
1. 只限于namespace或global作用域的变量常量。函数内或Class内的不做讨论。
2. 如果是C程序,以下涉及匿名namespace处都该以static取代之。(虽然C++也可以用static,但更好的方式是匿名namespace)
3. 链接期变量定义只能在一个CPP中出现;常量则可以多次出现。
4. 被置于namespace内的东西必将成为私用,编译器会帮你约束不小心的extern。
5. 共享的东西至少声明应该出现在头文件中,私用的东西则不该出现在头文件中

1. 私用:应该放在CPP中,常量和变量都应该以namespace{}或者static(如果是C程序)包含之,
// xx.cpp
namespace {
    int i = 100;
    const int i = 200;
}
当然如果不用namespace{}约束,并且头文件中不声明语法也是个私用变量:
但这样有两个风险:
1. 万一在头文件中声明extern了,编译器不会帮你检查
2. 对变量而言,容易与其他CPP产生变量定义冲突。
所以应该使用namespace{}约束之。

2. 给多个CPP共享:
变量应该以extern声明于头文件,普通定义于CPP文件。
常量应该以普通定义于头文件:
// xx.h
extern int i;
const int x = 100;
namespace { const int& b = x;  } // 注意引用并非编译其常量,故必须以namespace包含之。
// xx.cpp
int i = 10;

对于变量上面的方法仍可能产生链接期错误(如果另一个cpp有同名变量定义),那么你就不得不修改你的变量名,更好的方法是以非匿名的namespace约束之。如果此变量有可能在main()以外使用,那么你还不得不建立Meyers单件。

延伸讨论

1. 如果将匿名namespace置于头文件中会怎样?
首先虽然语法上不会招致错误,但绝不要这么做,因为逻辑上是自相矛盾的,你既想让位于匿名namespace中的东西私用,却又将其置于能够被他人共享的头文件中。
这么做的唯一后果就是在多个CPP中产生多份私用拷贝(无论对于常量还是变量),虽然这可能大大出乎你的意料(比如对于变量,你或许会认为可以在多个CPP中修改同一个变量)。

2. 如果将const定义于CPP中,再以extern const声明之,会怎样?
首先语法上虽然可以,但绝不要这么做。下列是针对extern const和直接定义const于头文件的一个比较:

用户习惯:后者更符合习惯,前者像从火星来的
效率:后者更高,因为做宏替换(编译期常量);前者成了运行期常量(其实值到运行期才能决定)
可维护性:前者更易维护(对实值得修改值影响本编译单元)。但是通常作为const的常量值更改的可能性很小(就像函数默认参数一样)。

所以更应该使用前者。

3. 运行期const不要置于头文件!

总结:
1. 首先应该尽量不要让名字暴露于全局空间,不论是变量还是常量
2. 头文件中绝不应该出现任何匿名namespace或者static(不包括定义与class定义式内的)
3. CPP文件中绝不应该出现非static(无论是常量或变量),除非是要extern 共享变量。
4. 应该这样做:
// .h
namespace var{
    extern int sharei; // 共享变量    
}
namespace con {
    const int shareci = 100; // 共享常量
}

// .cpp
namespace var {
    int sharei = 100;
}

namespace privateuse {
    namespace {
        int privatei = 10;
        const int privateci = 10;
        const int privateci = func(); 运行期const不要置于头文件!
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值