从类型为const char *的临时类型,无效初始化了类型为cost char *&的非常量引用

时间:2018-06-30 06:20:23

标签: c++ reference

编译以下程序后,出现此错误:

char const* func(char const* a, char const* b)
{
        return std::strcmp(a,b)<0?b:a;
}

char const*& func(char const*& a, char const*& b,char const*& c)
{
        return func(func(a,b),c);
}
int main()
{
    const char* a="First";
    const char* b="Second";
    const char* c="Third";

    func(func(a,b),c); //ERROR
    return 0;
}

问题:

1。。由于func(a,b)返回值而引发了错误,但我不知道原因。

2。为什么从func(char const *,char const *)返回时创建临时文件?是否创建它是因为调用方没有用于收集返回值的变量?

编辑:此错误已在其他线程中进行了讨论,但在这种情况下,情况有所不同(尽管希望的原因必须相同),因此我问了这个问题,因为在这种情况下解释不明显。请不要将其标记为重复。

1 个答案:

答案 0 :(得分:1)

起初,我误判了您的问题,因为我误读了您的代码。实际上,在您的代码中char const*& func(char const*& a, char const*& b,char const*& c)永远不会被调用;)

这部分代码实际上可以正常工作:

#include<cstring>
char const* func(char const* a, char const* b)
{
    return std::strcmp(a, b)<0 ? b : a;
}

#include<iostream>
int main()
{
    const char* a = "First";
    const char* b = "Second";
    const char* c = "Third";

    std::cout << func(func(a, b), c) << std::endl;
    std::cin.ignore();
    return 0;
}

返回“第三”

将main中的func(func(a, b), c)更改为func(a, b, c)时会产生问题。这是因为您正在组合指针和对指针的引用。这是可以做到的,但是做不到。

现在,如果您调用func(a, b, c),则所有参数都将通过引用传递给第二个函数 。为了演示这意味着什么,请考虑以下代码:

#include<iostream>
int main()
{
    const char* a = "First";
    std::cout << "a: " << (void*)a << ", &a:" << &a << std::endl;
    const char* b = "Second";
    std::cout << "b: " << (void*)b << ", &b:" << &b << std::endl;
    const char* c = "Third";
    std::cout << "c: " << (void*)c << ", &c:" << &c << std::endl;

    std::cin.ignore();
    return 0;
}    

对我来说,这返回:

a: 00938B30, &a:00B9FEEC
b: 00938BE4, &b:00B9FEE0
c: 00938BF4, &c:00B9FED4

看到了吗? a是一个指针,它包含一个地址,但也有一个指向a的地址。当您通过引用调用时,这些将被传递。

但是,在此(第二个func函数中,您调用的第一个func 复制指针值,因为它没有通过引用传递参数。这些本地副本是临时值,一旦函数超出范围,它们就会被销毁。发生问题的原因是第二个(func)函数尝试将此本地副本的地址写入引用所调用的值。

好的,我不知道您是否在这里关注我。让我们通过一个例子来演示内存中发生的事情:

#include<cstring>
#include<iostream>

char const* func(char const* const a, char const* const b)
{
    std::cout << "Func1:\n";
    std::cout << "local: a: " << (void*)a << "<--copy, &a:" << &a << "<--*different from main!*\n";
    std::cout << "local: b: " << (void*)b << "<--copy, &b:" << &b << "<--*different from main!*\n";
    return std::strcmp(a, b)<0 ? b : a;
}

char const*& func(char const*& a, char const*& b, char const*& c)
{
    std::cout << "Func2:\n";
    std::cout << "ref: a: " << (void*)a << "<--original, &a:" << &a << "<--original\n";
    std::cout << "ref: b: " << (void*)b << "<--original, &b:" << &b << "<--original\n";
    std::cout << "ref: c: " << (void*)c << "<--original, &c:" << &c << "<--original\n";
    char const* const out = func(func(a, b), c);
    std::cout << "Func2:\n";
    std::cout << "local: out: " << (void*)out << ", &out:" << &out << " (cannot return this local variable to a reference)\n";
    return c; // just to fix it for now
}

int main()
{
    std::cout << "Main:\n";
    const char* a = "First";
    std::cout << "a: " << (void*)a << ", &a:" << &a << "\n";
    const char* b = "Second";
    std::cout << "b: " << (void*)b << ", &b:" << &b << "\n";
    const char* c = "Third";
    std::cout << "c: " << (void*)c << ", &c:" << &c << "\n";

    func(a, b, c);
    std::cin.ignore();
    return 0;
}

对我来说,这返回:

Main:
a: 00F38D00, &a:005EF78C
b: 00F38C00, &b:005EF780
c: 00F38D08, &c:005EF774
Func2:
ref: a: 00F38D00<--original, &a:005EF78C<--original
ref: b: 00F38C00<--original, &b:005EF780<--original
ref: c: 00F38D08<--original, &c:005EF774<--original
Func1:
local: a: 00F38D00<--copy, &a:005EF5A4<--*different from main!*
local: b: 00F38C00<--copy, &b:005EF5A8<--*different from main!*
Func1:
local: a: 00F38C00<--copy, &a:005EF5A8<--*different from main!*
local: b: 00F38D08<--copy, &b:005EF5AC<--*different from main!*
Func2:
local: out: 00F38D08, &out:005EF680 (cannot return this local variable to a reference)

live demo

我希望这对你足够清楚