C包含引用的对向量的奇怪行为
作者:互联网
我刚发现一些非常奇怪的东西,看看这段代码:
#include <cstring>
#include <cstdio>
#include <utility>
#include <vector>
using namespace std;
class A {
public:
int n = 0;
A(const char* p) { n = strlen(p); };
A(A const&) = delete;
void operator=(A const&) = delete;
};
void F(vector<pair<const char*, const A&>> v) {
printf("F\n");
for(vector<pair<const char*, const A&>>::iterator it = v.begin();it!=v.end();++it) printf(" '%s': %p %i\n", it->first, &it->second, it->second.n);
};
int main(int, char**) {
F({
{ "A", "A" },
{ "B", "BB" },
{ "C", "CCC" },
{ "D", "DDDD" }
});
};
现在使用clang -std = c 11 -Wall -Wextra -Wpedantic -O0 main.cc -o main或类似的东西(禁用优化)编译它.
你应该看到这样的输出:
F
'A': 0x7fff57a0b988 1
'B': 0x7fff57a0b9d0 2
'C': 0x7fff57a0ba18 3
'D': 0x7fff57a0ba60 4
哪个好,编译器会自动创建矢量对象和相应的A&参考,都是不同的.
现在,使用clang -std = c 11 -Wall -Wextra -Wpedantic -O1 main.cc -o main编译它,注意我刚刚添加了最低级别的优化.
你会看到,
F
'A': 0x7fff5ac54b30 1629262454
'B': 0x7fff5ac54b30 1629262454
'C': 0x7fff5ac54b30 1629262454
'D': 0x7fff5ac54b30 1629262454
所有参数都引用相同的A&对象,我发现错了.
这是我的编译器细节:
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
这是预期的行为吗?这是编译器错误吗?
更新:
正如Matt McNabb所指出的那样,vectors和initializer_lists并不是设计用于const引用(尽管它在clang中编译得很好).但是,当写入与void F(vector< pair< char *,A&&>>){}相同的函数时,错误仍然存在.
解决方法:
你的代码似乎有点奇怪.你这样做:
void F(vector<pair<const char*, const A&>> v) {
所以你期望一个带有A对象引用的向量.但是你没有任何A物体.你传递的是字符串文字,编译器会隐式创建A对象 – 但这些是临时的,所以当你的函数体运行时,它们已经消失了,引用它们是未定义的行为,这就是为什么它适用 – O0,但不是-O1.
如果要隐式创建A对象然后保留它们,则不能使用引用.尝试
void F(vector<pair<const char*, const A>> v) {
标签:c,c11,language-lawyer,clang-2 来源: https://codeday.me/bug/20190823/1695104.html