C++ 字符串文字相等性检查?

C++ string literal equality check?

== 不是我们比较两个数组的方式,因为那只会比较地址:

#include <iostream>

int main()
{
  char a[] = "aaa";
  char b[] = "aaa";

  if (a == b)
    std::cout << "Yes" << std::endl;
  else
    std::cout << "No" << std::endl;

  return 0;
}

这段代码甚至给了我一个警告:

Array comparison always evaluates to false

但是当我尝试这样做时:

if ("aaa" == "aaa")

它似乎运行良好。仍然给我一个警告,但警告是:

Condition is always true

起初,我认为这是某种缓存的东西,所以我尝试了一个相当不寻常的字符串文字:

if ("whuiwhqohqweihqweohi" == "whuiwhqohqweihqweohi")

在 MSVC 和 g++ 上仍然可以正常工作。那是一种依赖于实现的行为吗?我知道比较在编译时已知的变量不是很有用,但我的问题只是 "how come this is the case?"。

此外,使用 auto 似乎也有效:

#include <iostream>

int main()
{
  auto a = "whuiwhqohqweihqweohi";
  auto b = "whuiwhqohqweihqweohi";
  if (a == b) {
    std::cout << "Yes" << std::endl;
  }
  else {
    std::cout << "No" << std::endl;
  }

  return 0;
}

此代码产生正确的输出。这里的ab是什么类型?

请不要回答"Use std::string"。与我的问题无关

这两个文字字符串是常量,编译器很可能会将您代码中的两个实例替换为一个实例,然后将其替换为 true。

autoabchar const*

为了

char a[] = "aaa";
char b[] = "aaa";

你比较本地数组ab的地址,所以不能有相同的地址。

为了

if ("aaa" == "aaa")

您比较 2 个可能相同或不同的静态字符指针。

来自string_literal

The compiler is allowed, but not required, to combine storage for equal or overlapping string literals. That means that identical string literals may or may not compare equal when compared by pointer.

bool b = "bar" == 3+"foobar" // could be true or false, implementation-defined

同案:

auto a = "whuiwhqohqweihqweohi";
auto b = "whuiwhqohqweihqweohi";

autoconst char*.

您在这里必须非常小心,因为您正在查看的某些情况与其他情况并不完全相同。

在你的第一个例子中:

char a[] = "aaa";
char b[] = "aaa";

if (a == b)

您正在创建两个 arrays char,每个都从字符串文字初始化。然后您将尝试将这些数组相互比较。在大多数情况下(包括本例),数组名称的计算结果为该数组中第一个元素的地址。所以你实际上是在比较两个数组的地址。那些不能相同,所以比较保证产生 false.

在您的第二个示例中:if ("aaa" == "aaa"),您比较的是字符串文字 本身 ,而不是从字符串文字初始化的数组。

标准不保证此结果。该标准允许(但不要求)将相同的字符串文字合并在一起。然而,您真正比较的不是文字的内容——而是它们存储的地址。如果编译器合并字符串文字使它们位于同一地址,这将产生 true。如果它让它们分开,它将产生 false.

在你的 auto 案例中:

auto a = "whuiwhqohqweihqweohi";
auto b = "whuiwhqohqweihqweohi";

您的情况几乎相同——ab 最终都作为指向 char 的指针,保存字符串文字的地址。如果编译器合并这些文字,它们将指向同一个地址,因此它们比较相等。如果编译器不将它们合并在一起,每个都有自己的地址,它们将比较不相等。

这里的要点是,其中 none 根本比较字符串的 内容 ,只是比较它们的存储地址。内容仅在两个字符串文字具有(或至少以)相同内容时才能合并的程度。

就 "at least end with" 而言,我指的是一个编译器,如果你有类似的东西:"wing" 在一个地方,"swing" 在另一个地方,编译器可以自由合并两者,因此代码如下:

auto a = "wing";
auto b = "swing";

...编译器可以将 swing 存储在一个地方,并初始化 a 以指向该存储文字的第二个字符。