C++ 为什么函数返回空字符串

C++ 为什么函数返回空字符串,c++,string,C++,String,为什么这个函数总是返回空字符串 我知道变量的作用域,但我认为函数将返回std::string res的副本 string getNumberOfLines(string absFilePath) { int nLines = 0; ifstream inFile(absFilePath.c_str()); if (!inFile) return "no lines"; char c; while (inFile.get(c))

为什么这个函数总是返回空字符串

我知道变量的作用域,但我认为函数将返回std::string res的副本

string getNumberOfLines(string absFilePath)
{
    int nLines = 0;
    ifstream inFile(absFilePath.c_str());

    if (!inFile)
        return "no lines";

    char c;
    while (inFile.get(c))
    {
        if (c == '\n')
            nLines++;
    }   

    string res;
    sprintf(&res[0], "%d lines.", nLines);
    puts(res.c_str()); // prints "40 lines" or etc.
    return res;
}

puts(getNumberOfLines("f.txt").c_str()); // outputs nothing

基本上,您试图写入一个空字符串


当您创建一个
std::string
时,没有分配任何存储空间,因此您将零长度数组的地址传递给
sprintf

,您使用
reference std::basic_string::operator[](size_t pos)
获取字符串中的第一个元素,然后使用
操作符获取其地址。但是,根据函数的规范,如果
pos==size
,则它是未定义的行为。C++11标准,草案N3337,[string.access]
基本字符串
元素访问(重点):


1要求:
pos
func(常量字符串和absFilePath)
将复制字符串,但
func(常量字符串和absFilePath)
不会
sprintf
不能以这种方式与
std::string
一起使用<代码>&res[0]
超出范围,因为字符串为空。一个好的调试编译器会为您标记这一点。改用
std::cin
。@NeilKirk谢谢你的建议。
func(字符串absFilePath)
是否也复制字符串?我经常看到
func(const string和absFilePath)
-为什么它是常量?为什么不正常地通过引用传递?防止复制字符串的是
&
。常量用于防止意外修改从外部传递给函数的字符串。调用者可能希望将其用于其他用途,并且由于它是一个输入参数,因此不希望它被函数更改。@NeilKirk啊,我现在明白了,这正是我所担心的-函数更改字符串。所以const确保函数不会更改字符串,而通过引用传递是为了提高效率(不复制)。效率是在编译时还是在运行时实现的?字符串可能在运行时才知道,因此这是一个运行时优化。“您正在传递零长度数组的地址”嗯,我对此不确定。在这一点之前,状态已经变得不明确。“不要使用C++”不是“C++中最好的实践是什么”的逻辑答案。LRIO很好地消除了咆哮,只留下了与问题实际相关的回答部分。“审查”?“尼尔科克,我很惊讶我们的C++ Valkiyy'自己没有纠正这个无法容忍的错误”。实际上,<代码>和RES(0)< /Cord>是UB,所以编译器在遇到它时可以自由地画胡子粉红。对于任何C++问题,标准是(没有双关语),你能引用这个标准吗?@ MGZZ为什么我们必须引用每一个事物的标准?那会很乏味。@NeilKirk:我们没有。只有那些标准授权被断言的事情。提供证据总比不提供好。@Mgetz你来了!然而,我同意柯克的观点,对于那些显而易见的人来说,这有时是一种过度的杀伤力。
std::ostringstream ss;
ss << nLines << " lines.";
auto res = ss.str();
std::cout << res << '\n';
return res;