- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
考虑以下具有两个编译单元的程序。
// a.hpp
class A {
static const char * get() { return "foo"; }
};
void f();
// a.cpp
#include "a.hpp"
#include <iostream>
void f() {
std::cout << A::get() << std::endl;
}
// main.cpp
#include "a.hpp"
#include <iostream>
void g() {
std::cout << A::get() << std::endl;
}
int main() {
f();
g();
}
出于某种原因需要创建全局字符串常量是很常见的。以完全天真的方式执行此操作会导致链接器问题。通常,人们将声明放在头文件中,将定义放在单个编译单元中,或者使用宏。
我的印象是这种使用函数的方式(如上所示)是“好的”,因为它是一个 inline
函数并且链接器消除了生成的任何重复拷贝, 使用这种模式编写的程序似乎运行良好。但是,现在我怀疑它是否真的合法。
函数 A::get
在两个不同的翻译单元中被 ODR 使用,但它是隐式内联的,因为它是一个类成员。
在 [basic.def.odr.6]
中声明:
There can be more than one definition of a ... inline function with external linkage (7.1.2)... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named
D
defined in more than one translation unit, then
- each definition ofD
shall consist of the same sequence of tokens; and
- in each definition ofD
, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition ofD
, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a non-volatile const object with internal or no linkage if the object has the same literal type in all definitions ofD
, and the object is initialized with a constant expression (5.19), and the object is not odr-used, and the object has the same value in all definitions ofD
; and
- in each definition ofD
, corresponding entities shall have the same language linkage; and
- ... (more conditions that don't seem relevant)If the definitions of
D
satisfy all these requirements, then the program shall behave as if there were a single definition ofD
. If the definitions ofD
do not satisfy these requirements, then the behavior is undefined.
在我的示例程序中,两个定义(每个翻译单元中一个)分别对应相同的标记序列。 (这也是我原本觉得还可以的原因。)
但是,不清楚是否满足第二个条件。因为,名称 “foo”
可能不对应于两个编译单元中的同一个对象——它可能是每个编译单元中的“不同”字符串文字,不是吗?
我尝试更改程序:
static const void * get() { return static_cast<const void*>("foo"); }
以便它打印字符串文字的地址,我得到相同的地址,但我不确定是否一定会发生。
它是否属于“...应引用在 D
的定义中定义的实体”? "foo"
是否被认为是在 A::get
中定义的?看起来可能是这样,但据我非正式理解,字符串文字最终会导致编译器发出某种全局 const char[]
,它位于可执行文件的特殊段中。该“实体”是否被认为在 A::get
内,还是不相关?
“foo”
是否甚至被视为“名称”,或者术语“名称”是否仅指代有效的 C++“标识符”,如可用于变量或函数?一方面它说:
[basic][3.4]
A name is a use of an identifier (2.11), operator-function-id (13.5), literal-operator-id (13.5.8), conversion- function-id (12.3.2), or template-id (14.2) that denotes an entity or label (6.6.4, 6.1).
标识符是
[lex.name][2.11]
An identifier is an arbitrarily long sequence of letters and digits.
所以看起来字符串文字不是名称。
另一方面,在第 5 节
[expr.prim.general][5.1.1.1]
A string literal is an lvalue; all other literals are prvalues.
一般来说,我认为 lvalues
是有名字的。
最佳答案
你最后的论点是胡说八道。 “foo”
在语法上什至不是一个名称,而是一个字符串文字。字符串文字是左值,一些具有名称的左值并不意味着字符串文字是或具有名称。代码中使用的字符串文字不违反 ODR。
实际上,在 C++11 之前,强制要求跨 TU 的内联函数的多个定义中的字符串文字指定相同的实体,但多余的且大部分未实现的规则已被 CWG 1823 删除.
Because, the name
"foo"
might not correspond to the same object in the two compilation units -- it's potentially a "different" string literal in each, no?
正确,但这无关紧要。因为 ODR 不关心具体的参数值。如果您确实设法以某种方式获得不同的例如要在两个 TU 中调用函数模板特化,这会产生问题,但幸运的是字符串文字是无效的模板参数,所以你必须要聪明点。
关于c++ - header 中的字符串——这是否违反了 ODR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37901693/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!