代码1
#include <iostream>
#include <functional>
#include<cstdio>
#include<cstring>
using namespace std;
class MyString3 {
public:
MyString3(const char * pChar=nullptr) {
if (pChar == nullptr) {
this->pString = new char[1];
this->pString[0] = '\0';
}
else {
int len = strlen(pChar);
this->pString = new char[len + 1];
strcpy(this->pString, pChar);
}
cout << "MyString 构造函数 函数地址"<<(int *)this << endl;
}
// 左值拷贝构造
MyString3(const MyString3 & _rval) {
int len = strlen(_rval.pString);
this->pString = new char[len + 1];
strcpy(this->pString, _rval.pString);
cout << "MyString 左值拷贝构造函数,原对象地址"<<(int *)(&_rval) <<"目标对象地址"<<(int *)(this) << endl;
}
//左值赋值重载函数
MyString3 & operator =(const MyString3 & _rval) {
cout << "MyString 左值赋值重载函数,原对象地址"<<(int *)(&_rval) <<"目标对象地址"<<(int *)(this) << endl;
if (this == &_rval) { return *this; }
else {
delete[]this->pString;
this->pString = nullptr;
int len = strlen(_rval.pString);
char *tep = new char[len + 1];
strcpy(tep,_rval.pString);
this->pString = tep;
return *this;
}
}
const char * c_str() {
return pString;
}
~MyString3() {
cout << "MyString 析构函数,析构函数对象地址"<<(int *)(this) << endl;
delete[] this->pString;
pString = nullptr;
}
private:
char *pString;
};
MyString3 getMyString(MyString3 & ms) {
const char * tep = ms.c_str();
MyString3 S(tep);
return S;
}
int main() {
MyString3 S1("ABCDEF123456");
MyString3 S2;
S2=getMyString(S1);
std::cout<<"S2对象地址"<<(int *)(&S2)<<std::endl;
system("pause");
return 0;
}



上面出现大量重复的空间开辟和析构过程.
如何解决上面的问题?
先回顾一下以前关于左值引用,和右值引用
int a =10;
int & ra=a;
左值,有名字,有地址 如a ,可以将左值引用绑定到一个左值上
int &b =100;//错误 不能将左值引用绑定到一个右值,100是右值
右值:没有名字,没有地址
int &&rb=100;//ok 将右值引用绑定到 右值
int &&rb=a;//错误,不能将右值引用绑定到左值
int &b =100 //错误, 如果要想可以 需要 const int &b =100; 编译器其实生成了一个 临时量 int tep=100; int &b=tep;
同理
// 不可以,因为C++编译器将匿名对象都看做右值,所以要 MyString3 && rs=MyString3;或者 const MyString3 &s=MyString3;
MyString3 &s=MyString3("ABC");
对于 C++编译器将匿名对象都看做右值,MyString3 &s=MyString3("ABC");
不同的编译器做法不一样,gcc编译器不允许,但是MSVC上可以 如下两张图


代码2
#include <iostream>
#include <functional>
#include<cstdio>
#include<cstring>
using namespace std;
class MyString3 {
public:
MyString3(const char * pChar=nullptr) {
if (pChar == nullptr) {
this->pString = new char[1];
this->pString[0] = '\0';
}
else {
int len = strlen(pChar);
this->pString = new char[len + 1];
strcpy(this->pString, pChar);
}
cout << "MyString 构造函数,对象地址"<<(int *)(this) << endl;
}
// 左值拷贝构造
MyString3(const MyString3 & _rval) {
int len = strlen(_rval.pString);
this->pString = new char[len + 1];
strcpy(this->pString, _rval.pString);
cout << "MyString 左值拷贝构造函数,原对象地址"<<(int *)(&_rval)<<"目标对象地址"<<(int *)(this) << endl;
}
// 右值拷贝构造, MyString3 && _rval 这个形参,右值引用 匹配 的是 临时对象
MyString3(MyString3 && _rval) {
//由于临时对象声明周期 只在当前语句,出了当前语句就销售了
//所以我们可以复用他开辟的堆空间,避免重复开辟
this->pString = _rval.pString;
_rval.pString = nullptr;//要置空,避免多个MyString 对象指向同一个堆空间
cout << "MyString 移动构造函数,原对象地址"<<(int*)(&_rval)<<"目标对象地址"<<(int *)(this) << endl;
}
//左值赋值重载函数
MyString3 & operator =(const MyString3 & _rval) {
cout << "MyString 左值赋值重载函数" << endl;
if (this == &_rval) { return *this; }
else {
delete[]this->pString;
this->pString = nullptr;
int len = strlen(_rval.pString);
char *tep = new char[len + 1];
strcpy(tep,_rval.pString);
this->pString = tep;
return *this;
}
}
//右值赋值重载函数 MyString3 && _rval 这个形参,右值引用 匹配 的是 临时对象
MyString3 & operator =(MyString3 && _rval) {
cout << "MyString 移动赋值重载函数,原对象地址"<<(int*)(&_rval)<<"目标对象地址"<<(int *)(this) << endl;
if (this == &_rval) { return *this; }
else {
//由于临时对象声明周期 只在当前语句,出了当前语句就销毁了
//所以我们可以复用他开辟的堆空间,避免重复开辟
this->pString = _rval.pString;
_rval.pString = nullptr;//要置空,避免多个MyString 对象指向同一个堆空间
return *this;
}
}
const char * c_str() {
return pString;
}
~MyString3() {
cout << "MyString 析构函数,析构对象地址"<<(int *)(this) << endl;
delete[] this->pString;
pString = nullptr;
}
private:
char *pString;
};
MyString3 getMyString(MyString3 & ms) {
const char * tep = ms.c_str();
MyString3 S(tep);
return S;
}
int main() {
MyString3 S1("ABCDEF123456");
MyString3 S2;
S2=getMyString(S1);
system("pause");
return 0;
}


通过右值引用,避免了一些内存重复开辟
代码3
MyString3 operator +(const MyString3 & ls,const MyString3 rs) {
char * tp = new char[strlen(ls.pString) + strlen(rs.pString) + 1];
strcpy(tp, ls.pString);
strcat(tp, rs.pString);
return MyString3(tp);
}
ostream & operator <<(ostream &out, const MyString3 & s) {
cout << s.c_str() << endl;
return out;
}
int main() {
MyString3 S1("ABCDEF");
MyString3 S2=("1234");
MyString3 S3 = S1 + S2;
cout << S3 <<"S3地址 ="<<&S3 << endl;
system("pause");
return 0;
}
在MyString 中加入 + 法操作,上面的 operator +()函数有问题, tp 没有 delete 内存泄漏了
修改如下
MyString3 operator+ (const MyString3 & ls, const MyString3 & rs) {
char * tp = new char[strlen(ls.pString) + strlen(rs.pString) + 1];
strcpy(tp, ls.pString);
strcat(tp, rs.pString);
MyString3 ts(tp);
delete[]tp;
cout << " operato + " << endl;
return ts;
}
//修改完成后 tp 指针能正常释放内存, 但是多构建了MyString3 ts(tp);对象,继续优化,执行结果如下第二张图
MyString3 operator+ (const MyString3 & ls, const MyString3 & rs) {
MyString3 ts;
ts.pString= new char[strlen(ls.pString) + strlen(rs.pString) + 1];
strcpy(ts.pString, ls.pString);
strcat(ts.pString, rs.pString);
cout << " operato + " << endl;
return ts;
}
MyString3 S3 = S1 + S2; //operator+ 返回的ts对象会使用 右值拷贝构造创建 S3,避免了像左值拷贝构造一样 一次堆内存的开辟


总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll