Line Line::operator =(Line ln) {
cout << "Assignment operator\n";
Line temp;
temp.ptr = new int;
*temp.ptr = *(ln.ptr);
return temp;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,执行以下语句时不会调用复制构造函数:
return temp;
Run Code Online (Sandbox Code Playgroud)
由于返回是按值,为什么不调用复制构造函数?
谢谢
我有一个方法,它返回一个字符串以显示为错误消息.根据程序中出现此错误的位置,我可能会在显示错误消息之前添加一些解释.
string errorMessage() {
return "this is an error";
}
// somewhere in the program...
const char* message = ("Some extra info \n" + errorMessage()).c_str();
cout << message << endl;
Run Code Online (Sandbox Code Playgroud)
(我将消息存储为const char*,因为我实际上会将此错误提供给另一个接受const char*参数的方法)
此时它输出垃圾(控制台上的不可打印的字符).
所以我玩了它,发现如果相反我做:
// somewhere in the program...
const char* message = ("Some extra info \n" + errorMessage()).c_str();
cout << ("Some extra info \n" + errorMessage()).c_str() << endl << message << endl;
Run Code Online (Sandbox Code Playgroud)
然后它会正确显示两次消息.
为什么提供额外的参数使其cout按我的意图工作?
我有以下代码:
std::vector<Info*> filter(int direction)
{
std::vector<Info*> new_buffer;
for(std::vector<Info*>::iterator it=m_Buffer.begin();it<m_Buffer.end();it++)
{
if(((*it)->direction == direction)
{
new_buffer.push_back(*it);
}
}
return new_buffer;
}
std::vector<Info*> &filteredInfo= filter(m_Direction);
Run Code Online (Sandbox Code Playgroud)
有人能解释一下这里发生了什么吗?过滤器方法是否会按值返回创建一个临时的,并且过滤后的信息永远不会被销毁,因为它的引用?
不确定我是否理解正确.在这种情况下,filteredInfo作为引用而不是一个引用之间的区别是什么?
例如,我有一个类在其consturctor中调用一个返回本地对象的函数.我正在尝试使用rvalue引用来访问此对象,以避免在内存中进行昂贵的移动.
class MyClass
{
BigObject&& C;
MyClass() : C(f())
{
};
};
BigObject f()
{
return BigObject();
}
Run Code Online (Sandbox Code Playgroud)
但是compiller告诉我,引用成员被初始化为一个临时的,在构造退出后不会持续存在.
我不明白.我理解在函数范围内创建的本地对象仅存在于函数范围内.到达范围的末尾 - 调用本地对象的析构函数.在这里,我用本地对象初始化rvalue引用,并且我可以访问它,而我在constuctor的主体中.
有人可以解释一下,这里发生了什么?有没有办法返回一个本地对象并将其用作任何ligetable类成员,而不是在内存中移动它?
我有一个处理和存储大量数据的函数,然后它将结果作为类的向量返回.存储在此函数中的数据量非常大,我希望在完成其工作后清除该函数的存储内存.是否有必要这样做(功能是否自动清除内存)还是应该通过某些功能清除内存?
更新:
vector<customers> process(char* const *filename, vector<int> ID)
{
vector<customers> list_of_customers;
(perform some actions)
return list_of_customers;
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试理解C++ 11中的移动语义,并且我编写了一小段代码来检查在创建对象时调用哪些构造函数.
这是代码:
#include <iostream>
using namespace std;
class Bar
{
public:
int b;
Bar();
Bar(const Bar&);
~Bar();
};
class Foo
{
public:
int d;
Bar* b;
Foo();
Foo(const Foo&);
Foo(Foo&& other);
~Foo();
Foo& operator = (Foo);
};
Foo test();
Foo::Foo()
{
cout << "Default ctr of foo called\n";
b = new Bar();
}
Foo::~Foo()
{
delete b;
}
Foo::Foo(const Foo& other)
{
cout << "Copy ctr of foo called\n";
d = other.d;
b = new Bar();
b->b = other.b->b; …Run Code Online (Sandbox Code Playgroud) 以下来自我的C++书籍的引文:
当我们使用直接初始化时,我们要求编译器使用普通函数匹配来选择与我们提供的参数最匹配的构造函数.当我们使用复制初始化时,我们要求编译器将右侧操作数复制到正在创建的对象中,必要时转换该操作数.
对我来说,这个粗体位会产生一些模糊性.它使得听起来像右手操作数被转换为类类型,然后使用复制构造函数,例如;
string s = "hello";
Run Code Online (Sandbox Code Playgroud)
会成为...
string s = string("hello");
Run Code Online (Sandbox Code Playgroud)
它使用复制构造函数.如果这是真的那么我的测试程序;
#include <iostream>
using namespace std;
class A{
public:
A(const A& b): data(b.data) { cout << "The first way" << endl;}
A(const char* c): data(c) { cout << "The second way" << endl;}
string data;
};
int main(){
A first("hello");
A second = "sup";
}
Run Code Online (Sandbox Code Playgroud)
应该产生"第二种方式,第二种方式,第一种方式".然而它反而打印出"第二种方式,第二种方式".从这里我可以得出结论它是使用const char*构造函数而不是复制构造函数.我会好的,除非后来说......
在复制初始化期间,允许编译器(但没有义务)跳过复制/移动构造函数并直接创建对象.也就是说,允许编译器重写
Run Code Online (Sandbox Code Playgroud)string null_book = "9-999-99999-9";成
Run Code Online (Sandbox Code Playgroud)string null_book("9-999-99999-9");但是,即使编译器省略了对复制/移动构造函数的调用,复制/移动构造函数也必须存在,并且必须在程序中的该点可访问(例如,非私有).
我不确定为什么复制构造函数甚至需要在这些示例中提及,否则
string null_book = "9-999-99999-9"
Run Code Online (Sandbox Code Playgroud)
总是隐含地意味着仍然使用const char*构造函数?实际上,我不需要定义复制构造函数以使上述工作正常.但是,如果我将"const A&"构造函数设置为私有(其他公共),那么我的程序将无法运行.为什么必须为不涉及它的隐式转换定义复制构造函数?什么构造函数"string null_book …
c++ copy-constructor implicit-conversion copy-initialization copy-elision
我很久以前就了解到,复制初始化会创建一个临时对象,然后用于初始化目标,尽管后者的复制构造函数已被优化掉;但编译器仍然假装使用它,检查是否存在并允许访问。
\n\n我注意到 Herb Sutter 在更新的 GOTW 帖子中提到,auto使用时这不再是正确的。
具体来说,Herb(2013 年撰写)仍然阐述了一般熟悉的规则:
\n\n\n\n\n如果
\nx是其他类型,从概念上讲,编译器首先将 x 隐式转换为临时小部件对象\xe2\x80\xa6 请注意,我在上面多次提到过 \xe2\x80\x9c 概念上\xe2\x80\x9d。\xe2\x80\x99s 因为实际上编译器被允许并且通常会优化来自GOTW #1 的临时 \xe2\x80\x94
他后来指出,当auto使用时(在 中auto w = x;),仅调用一个复制构造函数,因为没有x需要首先转换的方法。
如果函数返回迭代器(因此 it\xe2\x80\x99 是一个右值):
\n\n\n\n\n毕竟,正如我们在 GotW #1 中看到的,通常额外
\n=意味着两步 \xe2\x80\x9c 转换为临时的然后复制/移动 \xe2\x80\x9d 的复制初始化 \xe2\x80\x94 但请记住auto像这样使用时,\xe2\x80\x99t 不适用。\xe2\x80\xa6 急!不需要任何转换,我们直接构造i. \xe2\x80\x94 GOTW #2(强调我的)
如果从函数返回的类型与通过复制初始化初始化的变量的类型完全相同,则规则是临时变量被优化,但它仍然检查复制构造函数的访问。Herb 表示, 的情况并非如此auto,而是使用了直接初始化。
我正在尝试学习 C++ 中的资源管理,在我的研究中我遇到了一个有趣的优化。基本上,当使用复制构造函数初始化堆栈上的对象时,该对象是一个右值对象(它是右值对象吗?),而不是调用构造函数然后调用移动构造函数,编译器只是调用原始对象的构造函数。
Object c(Object(1)); // This is the same as Object c(1);
Object c(Object(Object(Object(Object(Object(1)))))); // This is also the same as Object c(1);
Run Code Online (Sandbox Code Playgroud)
Expected flow:
1. Object(1) calls the constructor and creates a nameless Object that will be removed as soon as it's created.
2. c notices this is an rvalue, and calls the move constructor.
3. Destructor for Object(1) is called.
Run Code Online (Sandbox Code Playgroud)
Actual flow:
1. c(1) is called.
Run Code Online (Sandbox Code Playgroud)
这很聪明,但是..如何?这个技巧背后的机制是什么?即使 Object 的构造函数接受指针和许多参数,这也有效。