首页
技术博客
PHP教程
数据库技术
前端开发
HTML5
Nginx
php论坛
新用户注册
|
会员登录
PHP教程
技术博客
编程问答
PNG素材
编程语言
前端技术
Android
PHP教程
HTML5教程
数据库
Linux技术
Nginx技术
PHP安全
WebSerer
职场攻略
JavaScript
开放平台
业界资讯
大话程序猿
登录
极速注册
取消
热门标签 | HotTags
main
controller
process
instance
metadata
cmd
email
spring
expression
char
random
bitmap
php5
merge
tags
match
frameworks
usb
request
post
bit
audio
flutter
php7
cpython
testing
format
text
web3
window
bytecode
python3
future
require
uml
int
config
httprequest
dockerfile
php
object
string
utf-8
range
copy
hashset
timezone
dagger
fetch
emoji
subset
settings
vba
tree
substring
integer
search
python
solr
join
header
lua
foreach
datetime
java
keyword
md5
uri
stream
triggers
sum
regex
hook
case
perl
express
io
replace
cPlusPlus
当前位置:
开发笔记
>
编程语言
> 正文
string对象被覆盖了,奇怪的问题!
作者:tuiqiu | 来源:互联网 | 2023-09-03 12:09
#include<stdio.h>#include<stdlib.h>#include<iostream>#include<string&
#include
#include
#include
#include
using namespace std;
string f() { return "hello";}
int main() {
const char * str = f().c_str();
cout << str<< endl;
string b = string("ppppp");
printf("str=[%p], b=[%p]\n", str, b.c_str());
cout << str << endl;
b = "ddddd";
cout << str << endl;
return 1;
}
结果是:
hello
str=[0x], b=[0x]
ppppp
ddddd
为什么不是:
hello
str=[0x], b=[0x]
hello
hello
?
百思不得其解
6 个解决方案
#1
我百思不得其解的是我都得不到你说的任何一种结果。
#2
什么骡子玩意?
#3
代码风格极其恶劣!
#4
函数 f 返回的临时对象已经被释放了。
#5
引用 1 楼 healer_kx 的回复:
我百思不得其解的是我都得不到你说的任何一种结果。
#6
条款22: 尽量用“传引用”而不用“传值”
c语言中,什么都是通过传值来实现的,c++继承了这一传统并将它作为默认方式。除非明确指定,函数的形参总是通过“实参的拷贝”来初始化的,函数的调用者得到的也是函数返回值的拷贝。
正如我在本书的导言中所指出的,“通过值来传递一个对象”的具体含义是由这个对象的类的拷贝构造函数定义的。这使得传值成为一种非常昂贵的操作。例如,看下面这个(只是假想的)类的结构:
class person {
public:
person(); // 为简化,省略参数
//
~person();
...
private:
string name, address;
};
class student: public person {
public:
student(); // 为简化,省略参数
//
~student();
...
private:
string schoolname, schooladdress;
};
现在定义一个简单的函数returnstudent,它取一个student参数(通过值)然后立即返回它(也通过值)。定义完后,调用这个函数:
student returnstudent(student s) { return s; }
student plato; // plato(柏拉图)在
// socrates(苏格拉底)门下学习
returnstudent(plato); // 调用returnstudent
这个看起来无关痛痒的函数调用过程,其内部究竟发生了些什么呢?
简单地说就是:首先,调用了student的拷贝构造函数用以将s初始化为plato;然后再次调用student的拷贝构造函数用以将函数返回值对象初始化为s;接着,s的析构函数被调用;最后,returnstudent返回值对象的析构函数被调用。所以,这个什么也没做的函数的成本是两个student的拷贝构造函数加上两个student析构函数。
但没完,还有!student对象中有两个string对象,所以每次构造一个student对象时必须也要构造两个string对象。student对象还是从person对象继承而来的,所以每次构造一个student对象时也必须构造一个person对象。一个person对象内部有另外两个string对象,所以每个person的构造也必然伴随另两个string的构造。所以,通过值来传递一个student对象最终导致调用了一个student拷贝构造函数,一个person拷贝构造函数,四个string拷贝构造函数。当student对象被摧毁时,每个构造函数对应一个析构函数的调用。所以,通过值来传递一个student对象的最终开销是六个构造函数和六个析构函数。因为returnstudent函数使用了两次传值(一次对参数,一次对返回值),这个函数总共调用了十二个构造函数和十二个析构函数!
在c++编译器的设计者眼里,这是最糟糕的情况。编译器可以用来消除一些对拷贝构造函数的调用(c++标准——见条款50——描述了具体在哪些条件下编译器可以执行这类的优化工作,条款m20给出了例子)。一些编译器也这样做了。但在不是所有编译器都普遍这么做的情况下,一定要对通过值来传递对象所造成的开销有所警惕。
为避免这种潜在的昂贵的开销,就不要通过值来传递对象,而要通过引用:
const student& returnstudent(const student& s)
{ return s; }
这会非常高效:没有构造函数或析构函数被调用,因为没有新的对象被创建。
通过引用来传递参数还有另外一个优点:它避免了所谓的“切割问题(slicing problem)”。当一个派生类的对象作为基类对象被传递时,它(派生类对象)的作为派生类所具有的行为特性会被“切割”掉,从而变成了一个简单的基类对象。这往往不是你所想要的。例如,假设设计这么一套实现图形窗口系统的类:
class window {
public:
string name() const; // 返回窗口名
virtual void display() const; // 绘制窗口内容
};
class windowwithscrollbars: public window {
public:
virtual void display() const;
};
每个window对象都有一个名字,可以通过name函数得到;每个窗口都可以被显示,着可以通过调用display函数实现。display声明为virtual意味着一个简单的window基类对象被显示的方式往往和价格昂贵的windowwithscrollbars对象被显示的方式不同(见条款36,37,m33)。
现在假设写一个函数来打印窗口的名字然后显示这个窗口。下面是一个用错误的方法写出来的函数:
// 一个受“切割问题”困扰的函数
void printnameanddisplay(window w)
{
cout << w.name();
w.display();
}
想象当用一个windowwithscrollbars对象来调用这个函数时将发生什么:
windowwithscrollbars wwsb;
printnameanddisplay(wwsb);
参数w将会作为一个windows对象而被创建(它是通过值来传递的,记得吗?),所有wwsb所具有的作为windowwithscrollbars对象的行为特性都被“切割”掉了。printnameanddisplay内部,w的行为就象是一个类window的对象(因为它本身就是一个window的对象),而不管当初传到函数的对象类型是什么。尤其是,printnameanddisplay内部对display的调用总是window::display,而不是windowwithscrollbars::display。
解决切割问题的方法是通过引用来传递w:
// 一个不受“切割问题”困扰的函数
void printnameanddisplay(const window& w)
{
cout << w.name();
w.display();
}
现在w的行为就和传到函数的真实类型一致了。为了强调w虽然通过引用传递但在函数内部不能修改,就要采纳条款21的建议将它声明为const。
传递引用是个很好的做法,但它会导致自身的复杂性,最大的一个问题就是别名问题,这在条款17进行了讨论。另外,更重要的是,有时不能用引用来传递对象,参见条款23。最后要说的是,引用几乎都是通过指针来实现的,所以通过引用传递对象实际上是传递指针。因此,如果是一个很小的对象——例如int——传值实际上会比传引用更高效。
string
include
io
ios
int
main
const
char
c语言
写下你的评论吧 !
吐个槽吧,看都看了
会员登录
|
用户注册
推荐阅读
char
Halcon之图像梯度、图像边缘、USM锐化
图像梯度、图像边缘、USM锐化图像梯度、图像边缘、USM锐化图像梯度、图像边缘、USM锐化图像卷积:1.模糊2.梯度3.边缘4.锐化1.视频教程:B站、 ...
[详细]
蜡笔小新 2024-11-12 21:40:43
main
统计输入整数中的正数和负数个数
本文提供了一个C++程序,用于读取一系列整数并统计其中正整数和负整数的个数。当输入为0时,程序结束。 ...
[详细]
蜡笔小新 2024-11-12 19:30:01
char
poj 3352 Road Construction
poj 3352 Road Construction ...
[详细]
蜡笔小新 2024-11-12 11:24:39
main
[c++基础]STL
cppfig15_10.cppincludeincludeusingnamespacestd;templatevoidprintVector(constvector&integer ...
[详细]
蜡笔小新 2024-11-13 13:22:43
text
c/c++常用代码doc,ppt,xls文件格式转PDF格式[转]
[转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ...
[详细]
蜡笔小新 2024-11-12 16:19:40
window
PHP 对象生命周期与内存管理
本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ...
[详细]
蜡笔小新 2024-11-12 13:35:26
match
检查在所有可能的“?”替换中,给定的二进制字符串中是否出现子字符串“10”带 1 或 0
检查在所有可能的“?”替换中,给定的二进制字符串中是否出现子字符串“10”带 1 或 0 ...
[详细]
蜡笔小新 2024-11-12 11:35:01
text
开机自启动的几种方式
0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ...
[详细]
蜡笔小新 2024-11-12 11:16:30
main
USACO ORZHDU_4277 DFS + STL + 枚举算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4277。作者:Bob Lee,日期:2012年9月15日。题目描述:给定n个木棍,求可以组成的不同三角形的数量,最多15根木棍。 ...
[详细]
蜡笔小新 2024-11-12 00:38:10
window
详解 Qt 串口通信程序全程图文 (4)
Qt串口通信程序全程图文是本文介绍的内容,本文一开始先讲解对程序的改进,在文章最后将要讲解一些重要问题。1、在窗口中加入一些组合框ComboBox ...
[详细]
蜡笔小新 2024-11-12 00:05:00
controller
Xcode 多项目联合调试技巧与实践
在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ...
[详细]
蜡笔小新 2024-11-11 18:24:27
main
[BZOJ2654] Tree 问题:二分查找与 Kruskal 算法结合的优化解决方案
题目《BZOJ2654: Tree》的时间限制为30秒,内存限制为512MB。该问题通过结合二分查找和Kruskal算法,提供了一种高效的优化解决方案。具体而言,利用二分查找缩小解的范围,再通过Kruskal算法构建最小生成树,从而在复杂度上实现了显著的优化。此方法不仅提高了算法的效率,还确保了在大规模数据集上的稳定性能。 ...
[详细]
蜡笔小新 2024-11-11 18:19:28
main
基础二分法在数据报告中的应用与优化
本文探讨了基础二分法在数据报告生成中的应用及其优化策略。通过分析二分法在处理大规模数据集时的高效性和准确性,提出了若干改进措施,以提升数据报告的生成速度和质量。具体包括算法的并行化处理、数据预处理技术的应用以及异常值的处理方法,旨在为数据分析师提供更为高效和可靠的工具。 ...
[详细]
蜡笔小新 2024-11-11 18:00:17
main
2018年湘潭大学程序设计竞赛在牛客网的时间数据分析报告
本报告对2018年湘潭大学程序设计竞赛在牛客网上的时间数据进行了详细分析。通过统计参赛者在各个时间段的活跃情况,揭示了比赛期间的编程频率和时间分布特点。此外,报告还探讨了选手在准备过程中面临的挑战,如保持编程手感、学习逆向工程和PWN技术,以及熟悉Linux环境等。这些发现为未来的竞赛组织和培训提供了 valuable 的参考。 ...
[详细]
蜡笔小新 2024-11-11 16:10:24
window
在 QQmlPropertyMap 的派生类中无法调用槽函数或 Q_INVOKABLE 方法?
在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ...
[详细]
蜡笔小新 2024-11-11 15:34:22
tuiqiu
这个家伙很懒,什么也没留下!
Tags | 热门标签
main
controller
process
instance
metadata
cmd
email
spring
expression
char
random
bitmap
php5
merge
tags
match
frameworks
usb
request
post
bit
audio
flutter
php7
cpython
testing
format
text
web3
window
RankList | 热门文章
1
基于Petri网的敏捷开发软件过程模型及实践1.引言
2
物联网浪潮即将来袭,创业者们你需要知道这些
3
Java开发基础——JSON数据的构造与解析
4
开发笔记:深入解析libgdx游戏框架中的开源Java系统控件Button类的专题15
5
backgroundposition和长图实现鼠标悬浮动画效果
6
(四十) git 打补丁方法总结
7
C语言头文件的使用(转载)
8
AVS30程序分析1
9
php批量验证类
10
Java如何判断数组是否相等呢?
11
cf右键属性兼容性中没有win8选项怎么?
12
第八章:异常控制流的重要性和应用
13
dll丢失怎么办?
14
php如何将字符串转换为bool类型
15
gitlab使用webhooks push事件,接收端重复收到通知
PHP1.CN | 中国最专业的PHP中文社区 |
DevBox开发工具箱
|
json解析格式化
|
PHP资讯
|
PHP教程
|
数据库技术
|
服务器技术
|
前端开发技术
|
PHP框架
|
开发工具
|
在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved |
京公网安备 11010802041100号
|
京ICP备19059560号-4
| PHP1.CN 第一PHP社区 版权所有