首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c++ inline 优化机理求剖解!

2014-03-13 
c++ inline 优化机理求剖析!!首先有一个结构体[解决办法]嘎嘎,心急可吃不了热豆腐啊~也就是说,函数返回的

c++ inline 优化机理求剖析!!
首先有一个结构体

 


[解决办法]


嘎嘎,心急可吃不了热豆腐啊~
也就是说,函数返回的 string 对象如果我不去接收的话,可能在调用 num2str 这行代码的下一行返回值就会被释放掉?
而且,如果我用 const string&  去接收的话,也是不能延长返回值的作用域的吧?期待高手你的回复!
如果我用 const string&  去接收的话,也是不能延长返回值的作用域的吧?
可以。如果你用const string& 就不会出现临时变量被提前销毁的问题。其实关于我说的临时变量,有个专业名词,叫做右值。对于这种右值,最新的C++标准还提出了右值引用来对其进行优化,以减少不必要的copy工作。
[解决办法]
引用:
Quote: 引用:

关于返回值, 有时候需要时T&(比如operator=), 其他时候用T就好(编译器有RVO/NRVO)

operator= 返回 string& 的话,我用 string 接收,会产生一次构造啊!
string t_oStrRecv = string("123");
这里应该会调用两次构造吧?

另外,
string getString(String str) {
    StringStream t_oStrStream;
    t_oStrStream << str << "-hahaha";
    return t_oStrStream.str();
}
...
const string& t_oStrRecv = getString("hehe");

用 const string& 接收 getString() 的返回值,可取么?是否也是不安全的做法,因为很可能返回值很快就被释放?


引用:
Quote: 引用:

关于返回值, 有时候需要时T&(比如operator=), 其他时候用T就好(编译器有RVO/NRVO)

operator= 返回 string& 的话,我用 string 接收,会产生一次构造啊!
string t_oStrRecv = string("123");
这里应该会调用两次构造吧?

另外,
string getString(String str) {
    StringStream t_oStrStream;
    t_oStrStream << str << "-hahaha";
    return t_oStrStream.str();
}
...
const string& t_oStrRecv = getString("hehe");

用 const string& 接收 getString() 的返回值,可取么?是否也是不安全的做法,因为很可能返回值很快就被释放?

我不是已经回答你了嘛,有人用这个变量,编译器自然就不会释放他。之前你的例子里有人用的不是函数返回的变量,而是返回变量的成员函数返回的变量,编译器可没那么智能,还是认为这个临时变量没人用。编译器判断某个右值有没有人用,就是看有没有哪个变量引用他。
其实我发现const string& t_oStrRecv和const string t_oStrRecv对于一些编译器没啥区别。现在的编译器已经有办法将const string t_oStrRecv优化到和const string& t_oStrRecv一个效果。



#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <tchar.h>
#include <string>
using namespace std;

struct MyStruct
{
MyStruct()
{
cout << "发生了构造" << endl;
};

MyStruct(const MyStruct &)
{
cout << "发生了拷贝" << endl;
}

MyStruct(const MyStruct &&)
{
cout << "发生了拷贝转移" << endl;
}

MyStruct operator = (const MyStruct &)
{
cout << "发生了赋值" << endl;
return MyStruct();
}

MyStruct operator = (const MyStruct &&)
{
cout << "发生了赋值转移" << endl;
return MyStruct();
}

void dosomething() const
{
cout << "Address:" << (int)this << endl;
}
};

MyStruct test1()
{
return MyStruct();
}

MyStruct test2()
{
MyStruct tmp;
tmp.dosomething();
return tmp;
}

int _tmain(int argc, _TCHAR* argv[])
{
const MyStruct & tmp = test2();
tmp.dosomething();
cout << "------分隔符------" << endl;
const MyStruct tmp2 = test2();
tmp2.dosomething();
system("pause");
return 0;
}

试试上面这个例子就知道了,我用vc2012编译的release版本运行结果为:
发生了构造
Address:1703091
Address:1703091
------分隔符------
发生了构造
Address:1703090
Address:1703090
请按任意键继续. . .
[解决办法]
引用:
Quote: 引用:
很多问题基础概念和原理搞清楚,问题就不存在了。不要本末倒置。

这是我实际遇到过的一个问题,环境是这样的
string num2str(int in_iNum) {
    string t_oStrRetVal;
    stringstream t_oStrStream;
    t_oStrStream << in_iNum;
    t_oStrStream >> t_oStrRetVal;
    return t_oStrRetVal;


}
void MyClass::test() {
    if (...) {
        ...
    } else {
        const char* tmp_pArrCharCount = num2str(100).c_str();
        printf("%s", tmp_pArrCharCount);
        ...
    }
}


结果 printf 打印出了其他的一些字符串
但是如果改写为
void MyClass::test() {
    if (...) {
        ...
    } else {
        string tmp_oStrCount = num2str(100).c_str();
        printf("%s", tmp_oStrCount.c_str());
        ...
    }
}

则能够打印出正确的东西来,能帮我分析一下为什么么?

num2str(100)得到一个匿名对象,可能会随时会失效。
string tmp_oStrCount = num2str(100).c_str();
或者string tmp_oStrCount = num2str(100);

tmp_oStrCount是有名对象,不会随时失效
[解决办法]
除了是应用还是拷贝的问题外
函数参数用const修饰,可以接受任何类型的变量,如果不用const修饰,不能接受const型的变量。
此外对于临时变量,你不要过多的去专牛角尖,临时变量的产生和销毁是根据编译器和优化级别的不同而不同的。很可能不会根据你认为的逻辑来进行创建和析构的,很多临时变量压根就不会产生,直接优化掉。所以如果你的逻辑实现依赖了临时变量的创建与销毁,要特别小心了。
[解决办法]
引用:
Quote: 引用:

对于入参,一般最好用const 的引用:
我所在的项目组,因为工程大,link时间过长,曾经花专人,用了好几个星期去优化项目,其中一个大头就是inline。 

其中一个大头就是 inline,怎么去优化这个东西呢?用宏?


没有什么好办法,对于一下无关紧要的接口等,都把它们提取到cpp里面去,缩小头文件被包含时候生成的目标文件的体积。用宏也未必是好事啊,我们的代码里面,有很大一块是template + 宏实现的底层框架,都没有人敢改。模板导致代码膨胀,你懂的

热点排行