【发布时间】:2014-11-30 11:35:32
【问题描述】:
我正在尝试用户定义的文字(我相信是在 gcc 4.7.1 中引入的),但对临时变量的工作方式感到困惑。
考虑以下代码:
#include <stdlib.h>
#include <iostream>
class Point
{
public:
Point(float x = 0, float y = 0, float z = 0)
:_x(x), _y(y), _z(z)
{
std::cout << "Constructor\n";
}
~Point()
{
std::cout << "Destructor\n";
}
Point& operator=(Point p)
{
std::cout << "Assignment op\n";
return *this;
}
Point& operator+(const Point& p)
{
std::cout << "Returning ref: operator+\n";
_x += p._x;
_y += p._y;
_z += p._z;
return *this;
}
void print() const
{
std::cout << "(" << _x << ", " << _y << ", " << _z <<")\n";
}
protected:
float _x, _y, _z;
};
Point operator "" _x(const char* l)
{
float x = atof(l);
std::cout<<"literal _x\n";
Point p(x);
return p;
}
Point operator "" _y(const char* l)
{
float y = atof(l);
std::cout<<"literal _y\n";
Point p(0, y);
return p;
}
Point operator "" _z(const char* l)
{
float z = atof(l);
std::cout<<"literal _z\n";
Point p(0, 0, z);
return p;
}
int main(int argc, char **argv)
{
Point& p = 12_x + 2_x + 3_y + 4_z;
p.print();
}
执行后我得到以下输出:
literal _z
Constructor
literal _y
Constructor
literal _x
Constructor
literal _x
Constructor
Returning ref: operator+
Returning ref: operator+
Returning ref: operator+
Destructor
Destructor
Destructor
Destructor
(14, 3, 4)
当我将行更改为Point& p = 12_x; 时,会发出一个错误,提示您无法从右值初始化引用。
当我将其更改为 const Point& p = 12_x; 时,我得到:
literal _x
Constructor
(12, 0, 0)
Destructor
我希望这两种情况中的任何一种,而不是第一种情况,所以我的问题是:第一种情况到底会发生什么?
附:我正在使用带有 gcc 4.8.1 的 MinGW。编译字符串:g++ --std=c++11 -Wall main.cpp -o out.exe
【问题讨论】:
-
引用本身没有存储空间(只有它所引用的地址)。因此,您不能引用表达式(右值)。为了解决这个问题,你必须产生一个变量
Point pp = ...,然后是Point &p = pp; -
[OT]:你现在可以使用
--std=c++11了。 -
您可以通过将您的运算符声明为 @987654331 来防止您的
operator+被应用于临时对象(这样它就不会将 非 const 左值引用返回到临时对象) @(即末尾多出一个 & 号) -
@PiotrS。或添加
Point& operator+(const Point&&) = delete; -
@JonathanWakely:但这将不允许:
Point& p = lvalue_of_point + 2_x;。但是,它是否应该起作用是有争议的,因为这里的主要问题是operator+是根据operator+=实现的