其他分享
首页 > 其他分享> > C包含引用的对向量的奇怪行为

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) {

示例:http://ideone.com/VNIgal

标签:c,c11,language-lawyer,clang-2
来源: https://codeday.me/bug/20190823/1695104.html