在警告级别3下,使用std::vector push_back插入int类型时编译器会发出警告。

5

我正在使用Intel C++编译器icc版本18.0.3。

如果我使用-w3编译以下代码

#include <vector>

int main() {
    std::vector<int> vec;
    vec.push_back(2);
    return 0;
}

test_w3.cpp(6): remark #383: 值被复制到临时位置,引用了临时位置 vec.push_back(2);

2替换为常量变量

#include <vector>
int main() {
    std::vector<int> vec;
    const int a = 2;
    vec.push_back(a);
    return 0;
}

没有提供警告。

这个警告是什么意思?它可以安全地忽略吗(尽管无警告的代码是可取的)?


如果向量在主函数外声明,或者打印结果,是否会得到相同的备注? - huseyin tugrul buyukisik
如果我打印它,仍然会给出备注。https://gcc.godbolt.org/z/atlYe6 - schorsch312
根据这篇文章intel-c-compiler/topic/300453,这个备注是不重要的,听起来应该已经被移除了,这可能是一个错误。 - George
如果我移动到一个函数,备注也仍然会被给出。https://gcc.godbolt.org/z/fKoED3 - schorsch312
它看起来真的像是一个错误的警告。即使你用 -Wall 替换 -w3,连 icc 也不会对相同的代码进行抱怨。 - Useless
1个回答

10

英特尔公司专门为这个问题提供了一个网站,其中包含与您的问题完全相同的链接。虽然该网站是2008年的,但似乎适用于您的问题。警告存在,因为这种编程风格可能会导致隐藏的临时对象,并且在某些情况下可以忽略

他们针对这个例子说明:

void foo(const int &var)
{
}

void foobar()
{
    std::vector<std::string> numlist
        // 383 remark here: a tempory object with "123" is created
        numlist.push_back("123");       
    foo(10);       // gives 383

}

以下内容:

解决方法:

  • 为初始化引用提供适当的对象。
  • 对于向量的pushback函数,可以安全地忽略此警告。 向量将参数复制到自己的存储中; 它从不存储原始参数。 因此,使用临时变量是完全安全的。

因此您可以忽略该警告,即使这违反了总体规则永远不要忽略警告

在我看来,英特尔选择了一种糟糕的方式,因为由误诊断引起的警告会阻碍开发。


9
忽略警告是一个非常糟糕的想法,因为这意味着真正的警告会淹没在误报警告中。这就是为什么这样的警告(很可能是误报)一开始就是个坏主意。这是一个不好的警告。应该在命令行选项中全局禁用它。 - Konrad Rudolph
4
我完全同意。 - user4290866
@KonradRudolph 我们添加了一个有关忽略警告的警告!感谢您的建议! - user4290866
在这里,实际上应该使用emplace_back(),不应该为此发出ICC警告(我不知道它是否会发出警告,但它不应该)。我的观点是只使用push方法来复制/移动现有实例(即不是临时的),但如果从构造函数参数创建新元素,则应通过emplace转发它们,而不是使用临时变量作为载体。对我来说,这既更清晰地表达了意图,又可以避免不必要的复制/移动 - 而且,我今天学到了,还可以避免警告! - underscore_d
@underscore_d,无论是push_back还是emplace_back都不应该发出警告,但它们确实会发出警告(https://gcc.godbolt.org/z/1BDtLX 是一个emplace_back的示例)。 - user4290866
@underscore_d 很抱歉,我误解了你的评论。是的,emplace_back会在原地创建整数。但对于提供的示例,这不会有任何区别 ;) - user4290866

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接