为什么 "auto" 声明字符串时会将其声明为 const char* 而不是 std::string?

13
我制作了一个模板,可以添加给定的数据。如果我像这样使用它,编译器会将in_1和in_2声明为const char *,此时代码无法编译。
#include <iostream>
using namespace std;
template <class T>
T addstuff(T part_1, T part_2){
    return(part_1+part_2);
}

int main(int argc, char const *argv[])
{
    auto in_1="Shut ";
    auto in_2="up.";
    cout<<addstuff(in_1, in_2)<<endl;
    return 0;
}

如果我声明in_1和in_2为std::string,它会像魅力一样运作。
为什么编译器不能(或不会)自动声明这些字符串为std::string?

5
为什么会这样呢?因为它们的类型不是std::string,而是const char(&)[N+1](其中N是字符串的长度)。 - user529758
8
这就是为什么我们需要字符串字面值(http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s)。虽然这是一个有点混乱的问题,但它表明了对 C++ 的期望已经提高了很多(并且它可以更加友好地用于初学者)。 - Benjamin Bannier
说句实话:你可以在C++11中自己实现字符串字面量后缀,无需等待。std::string operator"" _s(const char * str, size_t len) { return std::string{str, len}; } - Mark
4个回答

7

如果您使用字符串字面量,则 auto 将按预期工作。

在 C++14、C++17 或 C++20 中,您可以在引号后放置一个 s,它将创建一个 std::string 而不是一个 const char* 字符串。

这可以与 auto 一起使用来创建一个 std::string

auto hello = "hello"s;

字符串字面量默认是不启用的。启用字符串字面量的方法之一是将以下内容放置在源文件顶部:

#include <string>
using namespace std::string_literals;  

例如,这个循环适用于std::string(将s添加到字符串字面量中),但不适用于const char*类型的字符串字面量:

for (auto &x : hello) {                                                                        
    std::cout << "letter: " << x << std::endl;                                                         
}

这里是cppreference关于""s运算符的页面。点击这里查看。

5

你无法“写入”自动变量的原因是它是const char *或const char [1],因为这是任何字符串常量的类型。

auto的作用是解析为对于赋值类型最简单的可能类型。编译器不会“向前查看以了解您要使用该变量做什么”,因此它不理解您随后将要写入该变量,并使用它来存储字符串,所以std::string更合理。

您的代码可以通过许多不同的方式使其工作,以下是其中一种有意义的方式:

std::string default_name = "";
auto name = default_name;

cin >> name;

3
在第一段中,您可能希望将“字符串常量”更改为“字符串字面值”,因为“字符串常量”可能被合理地理解为一个常量std::string - user4815162342

4

由于字符串字面值的类型为const char[N+1],而不是std::string

这只是语言的一个事实。

他们本可以让auto针对字符串字面值有一个特殊情况,但那样会不一致、令人惊讶且几乎没有任何好处。


如果这个答案能解释一下为什么in_1没有类型const char[6]就更好了。 - M.M

0

auto 会将变量声明为初始化表达式的编译时类型。

字符串字面值的类型是 const char*,而不是 std::string


2
@H2CO3 - Joseph Mansfield
1
准确来说,字符串字面值的类型是const char [length + 1],但它们当然会衰变成指针。 - user529758

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