为什么返回的char不能由另一个char在一个简单表达式中直接分配

时间:2014-01-10 17:14:50

标签: c++

当我编译以下代码时:

#include <cstdio>

char retChar(){
    return 'c';
}

int main(){
    retChar() = 'f';
}

我收到了以下错误:

modify.cpp: In function ‘int main()’:
modify.cpp:8:14: error: lvalue required as left operand of assignment

我已经针对此错误搜索了类似的问题,但答案似乎只是针对具体情况。我还没有找到问题的答案。(也许在其他地方?)

=======================================添加======= ================================

但在以下情况中:

#include <iostream>

class int_Bag{
    int a;
    int b;
public:
    int_Bag(const int x, const int y);
    int_Bag(const int_Bag&c);
    int_Bag& operator =(const int_Bag &c){
        std::cout<< "copy assignment constructor called\n";
        a = c.a;
        b = c.b;
        return *this;
    }

    ~int_Bag();

    void debug();
};

int_Bag::int_Bag(const int x, const int y):a(x),b(y){}

int_Bag::~int_Bag(){
    std::cout<< "destructor called\n";
}

int_Bag::int_Bag(const int_Bag&c):a(c.a),b(c.b){
        std::cout<< "copy constructor called\n";
}

int_Bag getBag(const int_Bag &c){
    return c;
}

void int_Bag::debug(){
    std::cout << a <<"," << b << std::endl;
}

int main(){
    int_Bag *bag1 = new int_Bag(3,4);
    int_Bag *bag2 = new int_Bag(5,6);
    std::cout<< "assignment expression begins\n";
    getBag(*bag1) = *bag2;
    bag1->debug();
    delete bag1;
    delete bag2;
}

这个程序只是编译运行良好:

assignment expression begins
copy constructor called
copy assignment constructor called
destructor called
3,4
destructor called
destructor called

我们可以从结果中看到,当正在执行getBag()时,通过调用复制构造函数创建一个临时对象。所以我认为对于第一种情况,该赋值不起作用不仅仅是因为返回的char是临时的。

为什么作业getBag(*bag1) = *bag2;适用于此?

分配表达式的这两种情况有什么区别?

我认为,对于第二种情况,整个赋值表达式分为两个步骤:首先调用getBag()然后调用复制赋值将* bag2复制到getBag()返回的新创建的临时对象。但是,在第一种情况下,retChar()返回一个rvalue(也是临时的),它只能出现在赋值的RHS上,如@Jonathan Leffler所说。

第一种情况孤立似乎只是一个愚蠢的问题(我看到那些负面评论)。我刚刚添加的那些问题其实就是我真正感到困惑的问题。

期待收到关于我的supposal和其他anwsers的评论。

(来自c ++初学者^^)

4 个答案:

答案 0 :(得分:7)

您正在尝试修改临时(右值)。这是不可能的。

您可以通过几种方式实现目标,但最好的方法是:

int main()
{
    char c = retChar();
    c = 'f';
    // ...
    return 0;
}

您指的是具有getObject() = something的代码。该代码可能以某种形式编写,类似于:

char& getChar()
{
    static char c = 'c';
    return c;
}

int main()
{
    getChar() = 'f';
    // ...
    return 0;
}

返回引用(不是临时的)。当您将其分配到'f'时,cgetChar变量的值将变为'f'

答案 1 :(得分:5)

原始问题

您无法分配这样的函数的结果。该函数返回一个r值,这个值只能出现在赋值的RHS上。与可以分配给它的l值对比。

如果你真的想(你可能不这样做),你可以写:

char *retChar(){
    static char c = 'c';
    return &c;
}

int main(){
    *retChar() = 'f';
}

现在你已经修改了函数retChar()中的变量。


修正后的问题

此代码可以更加全面地完成您的示例:

#include <iostream>

class int_Bag
{
    int a;
    int b;
public:
    int_Bag(const int x, const int y);
    int_Bag(const int_Bag&c);
    int_Bag& operator =(const int_Bag &c){
        std::cout<< "copy assignment constructor called:\nold";
        this->debug();
        std::cout << "new";
        c.debug();
        a = c.a;
        b = c.b;
        return *this;
    }

    ~int_Bag();
    void debug() const;
};

int_Bag::int_Bag(const int x, const int y) : a(x), b(y)
{
    std::cout << "basic(" << x << "," << y << ")\n";
}

int_Bag::~int_Bag()
{
    std::cout << "destructor called";
    this->debug();
}

int_Bag::int_Bag(const int_Bag &c) : a(c.a), b(c.b)
{
    std::cout << "copy constructor called";
    this->debug();
}

int_Bag getBag(const int_Bag &c)
{
    std::cout << "getBag returns";
    c.debug();
    return c;
}

void int_Bag::debug() const
{
    std::cout << "(" << a << "," << b << ")" << std::endl;
}

int main()
{
    int_Bag *bag1 = new int_Bag(3, 4);
    int_Bag *bag2 = new int_Bag(5, 6);

    std::cout << "assignment expression begins\n";
    getBag(*bag1) = *bag2;
    std::cout << "assignment expression ended\n";
    bag1->debug();
    delete bag1;
    delete bag2;
}

当我运行它时,输出是:

basic(3,4)
basic(5,6)
assignment expression begins
getBag returns(3,4)
copy constructor called(3,4)
copy assignment constructor called:
old(3,4)
new(5,6)
destructor called(5,6)
assignment expression ended
(3,4)
destructor called(3,4)
destructor called(5,6)

5,6被分配给getBag()创建/返回的临时值,但随后被销毁。这些都不会影响3,4中的原始*bag1值。由getBag()创建的(匿名)对象在其出现的完整表达式结束之前可用,但不会超出,因此整个赋值仍然非常可疑。

我在Mac OS X 10.9.1 Mavericks上使用G ++ 4.8.2进行编译,在Ubuntu 13.10上使用G ++ 4.8.1编译,在这两种情况下使用选项:

g++ -O3 -g -std=c++11 -Wall -Wextra -Werror intbag.cpp -o intbag

编译器没有丝毫的杂音,valgrind 3.8.1也没有受到内存访问模式的影响。

我认为C ++会给你足够的绳索射击自己的脚,或者一些这样的混合比喻。

答案 2 :(得分:2)

您正在尝试为函数指定一个字符,这是不允许的!

我不确定你为什么认为这可能被允许,或者你为什么要这样做......

答案 3 :(得分:-1)

retChar()是一个功能。功能不像变量;它们不能分配给值。您的retChar()函数returns您可以在main方法中使用的char。例如,您可以这样做:

char myChar = retChar();

然后myChar将等于f

如果您发现自己对这些概念感到困惑,请尝试查看thisthis