当我编译以下代码时:
#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 ++初学者^^)
答案 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'
时,c
中getChar
变量的值将变为'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)