C++ &&

本文深入探讨了C++中的CopyElision与RVO优化技术,分析了这两种技术如何避免不必要的临时对象拷贝,减少内存开销,并介绍了右值引用如何进一步提高效率。

1右值引用引入的背景 
临时对象的产生和拷贝所带来的效率折损,一直是C++所为人诟病的问题。但是C++标准允许编译器对于临时对象的产生具有完全的自由度,从而发展出了CopyElision、RVO(包括NRVO)等编译器优化技术,它们可以防止某些情况下临时对象产生和拷贝。下面简单地介绍一下CopyElision、RVO

 

CopyElision-----------可以防止不必要的拷贝

 

1 struct A{ 
2 A(int){} 
3 A(constA&){} 
4 }; 
5 A a=42;

上面的创建对象的过程将会分为三步

第一步:为42创建一个临时的对象

第二部:以临时对象为参数拷贝构造a

第三部:析构临时对象

如果A是一个很大的类,那么临时对象的拷贝和析构将会造成很大的内存开销,为什么不直接将42为参数构造a,那么会省略临时对象需要的内存,

CopyElision就是解决这个问题的

 

测试编译器是否具有CopyElision优化功能:

手写A类的拷贝构造函数(拷贝函数中加打印字符),如果上述没有执行拷贝,说明编译器支持copyelision优化技术

 

-------------------------------------------------------------------------------------------------------------------------------------------------------

RVO返回值优化技术

 

struct A
{
    A(int) {}
    A(const A&) {}
};
A get()
{
    return A(1);
    // tmp1(1)
}
A a=get();//tmp2

上述代码中,首先会在get函数中产生一个临时对象tmp1,之后以tmp1为参数拷贝构造返回值tmp2,在最后一句中有产生了临时对象tmp2,之后以tmp2为参数拷贝构造a对象

RVO技术就是解决了这种返回值产生的临时对象的拷贝和内存开销

 

测试,同样可以在代码中手写拷贝构造函数添加输出语句进行测试,如果没有输出,说明编译器支持RVO优化技术

*************************

上述两种优化,如果编译器都支持,虽然不会调用拷贝构造函数,但是拷贝构造函数必须有访问权限,如果写在private里面,编译器会报错

******************

除了返回值优化,你可能还听说过一个叫具名返回值优化(NamedReturnValueOptimization,NRVO)的优化技术,从程序员的角度而言,它其实跟RVO同样的逻辑。只是它的临时对象具有变量名标识,例如修改上述get()函数为: 

1 A get()
2 {
3     A tmp(1);//#1
4 
5     return tmp;
6 }
7 A a=get();//#2

想想上述修改后A类型共有几次对象构造?虽然#1处看起来有一次显示地构造,#2处看起来也有一次显示地构造,但如果你的编译器支持NRVO和CopyElision,你会发现整个Aa=get();语句的执行过程,只有一次A对象的构造。如果你在get()函数return语句前打印tmp变量的地址,在Aa=get();语句后打印a的地址,你会发现两者地址相同,这就是应用了NRVO技术的结果。 

 

template<typename T>
void swap(T &a,T &b)
{
    T tmp(a);
    a=b;
    b=tmp;
}

我们只是想交换a和b两个对象所拥有的数据,但却不得不使用一个临时对象tmp备份其中一个对象,如果T类型对象拥有指向(或引用)从堆内存分配的数据,那么深拷贝所带来的内存开销是可以想象的。为此,C++11标准引入了右值引用,使用它可以使临时对象的拷贝具有move语意,从而可以使临时对象的拷贝具有浅拷贝般的效率,这样便可以从一定程度上解决临时对象的深度拷贝所带来的效率折损。 

//参考  http://www.jb51.net/article/32000.htm !!!!!

 

转载于:https://www.cnblogs.com/13224ACMer/p/6106963.html

<think>好的,我需要回答用户关于C++中`&&=`和`&=`运算符的用法和区别的问题。首先,我应该确认这两个运算符在C++中是否存在,因为可能用户混淆了其他语言中的运算符。 首先,`&=`是常见的按位与赋值运算符,在C++中确实存在。例如,`a &= b;`等价于`a = a & b;`,其中`&`是按位与操作。这一点我比较确定,可以引用参考中的信息,比如引用[1]提到`&&`用于布尔表达式,而`&`用于按位操作。 接下来,`&&=`这个运算符是否存在?根据我的知识,C++中并没有`&&=`运算符。用户可能将其他语言(比如Ruby或某些脚本语言)中的运算符混淆到C++中了。需要指出这一点,避免误导。 然后,用户可能对逻辑与赋值操作有疑问,但C++中并没有`&&=`,只有逻辑与运算符`&&`。因此需要解释清楚`&&`和`&`的区别,以及它们对应的赋值运算符`&=`的存在情况。 另外,参考中提到了`&&`仅用于布尔表达式,而`&`用于按位操作,这与C++的标准一致。需要结合这些引用内容来增强回答的可信度。 可能还需要举例说明`&=`的用法,比如操作整数进行按位与赋值,而逻辑与`&&`没有对应的赋值运算符,因为逻辑运算的结果是布尔值,直接赋值可能不符合预期。 总结步骤: 1. 确认`&=`存在并解释其用法。 2. 指出`&&=`在C++中不存在。 3. 比较`&`和`&&`的区别,引用参考内容。 4. 提供示例代码说明`&=`的正确用法。 5. 提醒用户可能的混淆来源,如其他语言的影响。</think>### C++中`&=`与`&&=`运算符的区别 #### 1. **`&=`运算符的用法** - **定义**: `&=`是**按位与赋值运算符**,等价于先进行按位与运算后赋值,例如: ```cpp int a = 5; // 二进制 0101 a &= 3; // 等价于 a = a & 3(3的二进制为 0011) // 结果a = 1(二进制 0001) ``` - **适用类型**: 只能用于整数类型(如`int`, `char`, `unsigned`等),不能直接用于布尔表达式[^1]。 #### 2. **`&&=`在C++中不存在** - **误区澄清**: C++标准**没有定义`&&=`运算符**。用户可能混淆了其他语言(如Ruby)的逻辑与赋值语法。 - **替代实现**: 若需要类似逻辑与赋值的效果,需显式拆分: ```cpp bool flag = true; flag = flag && (x > 0); // 正确写法 ``` #### 3. **`&`与`&&`的核心区别** - **按位与`&`**: 对整数的二进制逐位操作,例如: $$5\,\&\,3 = 1$$ - **逻辑与`&&`**: 仅作用于布尔表达式,短路特性(若左侧为`false`则右侧不计算): ```cpp if (x > 0 && y < 10) { ... } ``` #### 示例代码 ```cpp #include <iostream> using namespace std; int main() { int a = 0b1010; // 二进制10 a &= 0b1100; // 结果a=0b1000(十进制8) cout << a << endl; bool b = true; b = b && (a == 8); // 逻辑与赋值的手动实现 cout << boolalpha << b << endl; return 0; } ``` #### 注意事项 - 误用`&`代替`&&`会导致逻辑错误(如`if (x & y)`可能非预期)。 - 赋值运算符的优先级较低,必要时需加括号。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值