为什么地址运算符获得的指针不是左值?

时间:2012-12-05 19:24:28

标签: c++ c

我很想知道为什么C ++中不允许使用&a = &b之类的作业。

我理解这样做的风险,但至少对我来说完全禁止它是不够的理由。我之所以这么想是因为我正在寻找一种不用复制来交换大对象的聪明方法,而这样的东西似乎是一个好主意:

void ptr_swap( ptrdiff_t &a, ptrdiff_t &b )
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

int main()
{
    double a = 157648.13;
    double b = 96871.84;

    printf("%.4f %.4f\n", a, b);

    ptr_swap( reinterpret_cast<ptrdiff_t>(&a), reinterpret_cast<ptrdiff_t>(&b) );

    printf("%.4f %.4f\n", a, b);
}

..但显然,编译器并不这么认为。 :(

编辑:我理解为什么这不起作用。也许我的问题会更清楚:我不知道变量在一个程序中有多少属性,但至少有一个名称,一个值,一个地址,以及它的生命周期的一些指示。问题是,对我来说,交换本质上是重命名存储在内存中的两个现有值,并且它会产生副本是无稽之谈。

我放弃了这个“可怕的”代码示例,我要做的就是对编译器说:“从现在开始,b被命名为a,反之亦然”。为什么这样的事情不可能?动机是,已经可以通过TMP以某种方式“指导编译器”,所以为什么不这样呢?

5 个答案:

答案 0 :(得分:9)

在我看来,你想改变一个物体的地址,对吧?那是不可能的。每个对象在其整个生命周期中都有固定的地址。您永远不能为对象提供不同的地址。对象的地址隐含在生成的机器代码中,它本身并未存储在任何地方。

答案 1 :(得分:3)

&是一个运算符,其值为结果。你会如何为某个值赋值?例如:

int i, n;
i + n = 50;

答案 2 :(得分:2)

已经有很多其他方法可以做到这一点,为什么还有一个方法比其他方法更差?你可以用智能指针完美地完成这个任务。

答案 3 :(得分:1)

从问题的顶部开始:

Why are pointers obtained by the address-of operator not lvalues?

根据c99标准,

ISO : c99 6.5.3.2 Address and indirection operators

语义

3
The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the **result is not an lvalue**.

暂时是一个物体的财产。 当你创建一个对象的引用时,它只是临时的,你不能为其他变量重新定义它。

现在,您所做的是passing by address而不是passing by reference。 对于pass by reference,只需要传递变量,因此在调用环境中不需要&

只需这样做:

 swap(a,b); // calling

void swap(int &a, int &b)
{
 // definition 
 // here a and b are reference.
}

答案 4 :(得分:1)

对象是内存中的位置 变量名是对象的引用(一种引用程序中对象的方法)。并非所有变量都有名称。

但是你可以通过将别名传递给你的变量来实现你想要的东西:

void print(double& ref1, double& ref2)
{
    printf("%.4f %.4f\n", ref1, ref2);
}
int main()
{
    double a = 157648.13;
    double b = 96871.84;

    print(a, b);    
    print(b, a); // Pass them the function the other way around.
                 // You have effectively swapped the values (as far as the function is concerned).
}

在我的选项中,您正在尝试解决不存在的问题。