这是一个小代码片段:
class A
{
public:
A(int value) : value_(value)
{
cout <<"Regular constructor" <<endl;
}
A(const A& other) : value_(other.value_)
{
cout <<"Copy constructor" <<endl;
}
private:
int value_;
};
int main()
{
A a = A(5);
}
Run Code Online (Sandbox Code Playgroud)
我假设输出将是"常规构造函数"(对于RHS),后面是LHS的"复制构造函数".所以我避免使用这种风格并始终将类的变量声明为A a(5);.但令我惊讶的是上面的代码从未调用过复制构造函数(Visual C++ 2008)
有没有人知道这种行为是由编译器优化,还是C++的一些记录(和可移植)功能引起的?谢谢.
以下代码仅在复制构造函数可用时有效.
当我添加print语句(via std::cout)并使复制构造函数可用时,它不会被使用(我假设有这样的编译器技巧,以删除不必要的副本).
但是在输出operator <<和plop()下面的函数(我创建一个临时对象)中我都没有看到复制构造函数的需要.当我通过const引用(或者我做错了)传递所有内容时,有人可以解释为什么语言需要它.
#include <iostream>
class N
{
public:
N(int) {}
private:
N(N const&);
};
std::ostream& operator<<(std::ostream& str,N const& data)
{
return str << "N\n";
}
void plop(std::ostream& str,N const& data)
{
str << "N\n";
}
int main()
{
std::cout << N(1); // Needs copy constructor (line 25)
plop(std::cout,N(1)); // Needs copy constructor
N a(5);
std::cout << a;
plop(std::cout,a);
}
Run Code Online (Sandbox Code Playgroud)
编译:
[Alpha:〜/ X] myork%g ++ -v
使用内置规格.
目标:i686-apple-darwin10
配置:/ var/tmp/gcc/gcc-5646~6/src/configure --disable-checking --enable-werror --prefix …
我需要编写一个复制构造函数,深度复制一个内容std::shared_ptr.但是,int a, b, c, d, e;在类中还定义了一堆变量.有没有办法在我的新重载的代码中生成默认的复制构造函数代码(或调用默认的复制构造函数).
这是一个带有注释的代码片段,希望能够澄清问题.
class Foo {
public:
Foo() {}
Foo(Foo const & other);
...
private:
int a, b, c, d, e;
std::shared_ptr<Bla> p;
};
Foo::Foo(Foo const & other) {
p.reset(new Bla(*other.p));
// Can I avoid having to write the default copy constructor code below
a = other.a;
b = other.b;
c = other.c;
d = other.d;
e = other.e;
}
Run Code Online (Sandbox Code Playgroud) 我正在创建一个具有多种不同节点类型的树:二进制节点,一元节点和终端节点.我有一个所有节点继承的ABC.我正在尝试为树编写递归复制构造函数,如下所示:
class gpnode
{
public:
gpnode() {};
virtual ~gpnode() {};
gpnode(const gpnode& src) {};
gpnode* parent;
}
class bnode:gpnode
{
public:
bnode() {//stuff};
~bnode() {//recursive delete};
bnode(const bnode& src)
{
lnode = gpnode(src.lnode);
rnode = gpnode(src.rnode);
lnode->parent = this;
rnode->parent = this;
}
gpnode* lnode;
gpnode* rnode;
}
class unode:gpnode
{
public:
unode() {//stuff};
~unode() {//recursive delete};
unode(const unode& src)
{
node = gpnode(src.node);
node->parent = this;
}
gpnode* node;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我做不到
node = gpnode(src.node);
Run Code Online (Sandbox Code Playgroud)
因为gpnode是一个虚拟类.我可以
node = unode(src.node);
Run Code Online (Sandbox Code Playgroud)
但是当unode的子节点是bnode时,这不起作用.如何让它智能地调用我需要它的复制构造函数?
我已经看到了对C++中STL字符串的复制构造函数行为的各种冲突引用,我希望有人可以为我澄清这一点,给出以下代码段:
string str() { return string("this is a string"); }
//meanwhile, in some other function...
string s = str();
Run Code Online (Sandbox Code Playgroud)
对象''是否构成函数'str()'中定义的字符串对象的深层副本?或者是对象''简单地指向在'str()'函数中的字符串构造函数调用期间分配的同一块内存?
根据我的理解,我可以通过定义私有拷贝构造函数和赋值运算符来"禁用"复制和分配给我的对象:
class MyClass
{
private:
MyClass(const MyClass& srcMyClass);
MyClass& operator=(const MyClass& srcMyClass);
}
Run Code Online (Sandbox Code Playgroud)
但这有什么用呢?
它被认为是一种不好的做法吗?
如果您能够描述这种情况,我将不胜感激,以这种方式"禁用"赋值和复制构造函数是合理/有用的.
我遇到了一些我不清楚的异常问题.在C++中,当抛出一个对象时,它首先被复制到一个临时对象,然后临时对象被传递给捕获代码.该副本涉及使用对象的类复制构造函数.AFAIK,这意味着如果一个类有一个私有拷贝构造函数,它就不能用作异常.但是,在VS2010中,以下代码编译并运行:
class Except
{
Except(const Except& other) { i = 2; }
public:
int i;
Except() : i(1) {}
};
int main()
{
try
{
Except ex1;
throw ex1; // private copy constructor is invoked
}
catch (Except& ex2)
{
assert(ex2.i == 2); // assert doesn't yell - ex2.i is indeed 2
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这合法吗?
很少会遇到一个不包含原始指针的类,但默认的复制构造函数是不够的.例如,当您有一个引用计数对象时.boost :: shared_ptr <>就是一个例子.
有人可以详细说明吗?如果我们有一个包含a的类boost::shared_ptr,那么当类被构造复制时,不会构造复制 - 因此shared_ptr构造函数不会做正确的事情并增加引用计数吗?例如,下面的代码Inner正确复制- 为什么这不适用shared_ptr?:
#include <iostream>
using namespace std;
class Inner
{
public:
Inner() { cout << "inner default constructed" << endl;}
Inner(const Inner& other) { cout << "inner properly copied" << endl;}
};
class Outer
{
Inner i;
};
int main() { Outer o; Outer p(o); return 0;}
Run Code Online (Sandbox Code Playgroud) 考虑以下程序:
#include <iostream>
#include <utility>
class T {
public:
T() { printf("address at construction: %zx\n", (uintptr_t)this); }
// T(const T&) { printf("copy-constructed\n"); } // helps
// T(T&&) { printf("move-constructed\n"); } // helps
// T(const T&) = default; // does not help
// T(T&&) = default; // does not help
};
T f() { return T(); }
int main() {
T x = f();
printf("address after construction: %zx\n", (uintptr_t)&x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时g++ -std=c++17 test.cpp给出以下输出(与之相同clang++):
address at …Run Code Online (Sandbox Code Playgroud) 编译器生成一些类方法,如复制构造函数,析构函数等.是否有可能让gdb中断这些方法,例如,观察对象被复制或销毁的位置?
c++ ×10
copy-constructor ×10
constructor ×2
shared-ptr ×2
c++17 ×1
copy-elision ×1
debugging ×1
deep-copy ×1
destructor ×1
exception ×1
gdb ×1
inheritance ×1
memory ×1
private ×1
string ×1