复制构造函数的这种实现有一些缺点吗?
Foo::Foo(const Foo& i_foo)
{
*this = i_foo;
}
Run Code Online (Sandbox Code Playgroud)
我记得,在某些书中建议从赋值运算符调用复制构造函数并使用众所周知的交换技巧,但我不记得了,为什么......
在我学习C++的过程中,我偶然发现了编写复制构造函数和赋值运算符的文章,该文章提出了一种机制来避免复制构造函数和赋值运算符之间的代码重复.
为了总结/复制该链接的内容,建议的机制是:
struct UtilityClass
{
...
UtilityClass(UtilityClass const &rhs)
: data_(new int(*rhs_.data_))
{
// nothing left to do here
}
UtilityClass &operator=(UtilityClass const &rhs)
{
//
// Leaves all the work to the copy constructor.
//
if(this != &rhs)
{
// deconstruct myself
this->UtilityClass::~UtilityClass();
// reconstruct myself by copying from the right hand side.
new(this) UtilityClass(rhs);
}
return *this;
}
...
};
Run Code Online (Sandbox Code Playgroud)
这似乎是避免代码重复同时确保"编程完整性"的好方法,但需要权衡浪费工作的风险 - 然后分配嵌套内存,而不是重新使用(正如其作者指出的那样).
但我不熟悉其核心语法:
this->UtilityClass::~UtilityClass()
Run Code Online (Sandbox Code Playgroud)
我假设这是一种调用对象的析构函数(破坏对象结构的内容)同时保持结构本身的方法.对于C++新手来说,语法看起来像是对象方法和类方法的奇怪混合.
有人可以向我解释这个语法,还是指向一个可以解释它的资源?
该呼叫与以下内容有何不同?
this->~UtilityClass()
Run Code Online (Sandbox Code Playgroud)
这是合法的电话吗?这是否会破坏对象结构(没有堆;从堆栈中弹出)?
我有一个使用std :: thread将数据传递到线程的问题.我以为我理解了复制构造函数等的一般语义,但似乎我并没有完全理解这个问题.我有一个名为Log的简单类,它隐藏了它的复制构造函数:
class Log
{
public:
Log(const char filename[], const bool outputToConsole = false);
virtual ~Log(void);
//modify behavior
void appendStream(std::ostream *);
//commit a new message
void commitStatus(const std::string str);
private:
//members
std::ofstream fileStream;
std::list<std::ostream *> listOfStreams;
//disable copy constructor and assignment operator
Log(const Log &);
Log & operator=(const Log &);
}
Run Code Online (Sandbox Code Playgroud)
int main()
{
static int portNumber = 10000;
Log logger("ServerLog.txt", true);
logger.commitStatus("Log Test String");
try {
boost::asio::io_service ioService;
server(ioService, portNumber, logger);
}
catch (std::exception &e)
{ …
Run Code Online (Sandbox Code Playgroud) 可变构造函数是否应该隐藏隐式生成的构造函数,即默认构造函数和复制构造函数?
struct Foo
{
template<typename... Args> Foo(Args&&... x)
{
std::cout << "inside the variadic constructor\n";
}
};
int main()
{
Foo a;
Foo b(a);
}
Run Code Online (Sandbox Code Playgroud)
不知何故,我希望在阅读这个答案之后不打印任何内容,但它会inside the variadic constructor
在g ++ 4.5.0上打印两次:(这种行为是否正确?
它也没有可变参数模板:
struct Foo
{
Foo()
{
std::cout << "inside the nullary constructor\n";
}
template<typename A> Foo(A&& x)
{
std::cout << "inside the unary constructor\n";
}
};
int main()
{
Foo a;
Foo b(a);
}
Run Code Online (Sandbox Code Playgroud)
同样,两行都打印出来.
假设您有一个类型对象T
和一个适当对齐的内存缓冲区alignas(T) unsigned char[sizeof(T)]
.如果您使用std::memcpy
从类型对象复制T
到unsigned char
数组,是否考虑复制构造或复制分配?
如果一个类型可以轻易复制而不是标准布局,那么可以想象一个类如下:
struct Meow
{
int x;
protected: // different access-specifier means not standard-layout
int y;
};
Run Code Online (Sandbox Code Playgroud)
可以像这样实现,因为编译器不会被强制使用标准布局:
struct Meow_internal
{
private:
ptrdiff_t x_offset;
ptrdiff_t y_offset;
unsigned char buffer[sizeof(int) * 2 + ANY_CONSTANT];
};
Run Code Online (Sandbox Code Playgroud)
编译器可以存储x
和y
喵的缓冲器内的任何部分buffer
,甚至可能在随机内的偏移buffer
,只要它们被适当地对准和不重叠.的偏移x
和y
可即使编译愿与各施工随机变化.(如果编译器希望,x
可以继续y
使用,因为标准只要求相同访问说明符的成员按顺序排列,x
并且y
具有不同的访问说明符.)
这将符合可轻易复制的要求; a memcpy
将复制隐藏的偏移字段,因此新副本将起作用.但有些事情是行不通的.例如,持有指向x
跨越a 的指针memcpy
会破坏:
Meow a;
a.x …
Run Code Online (Sandbox Code Playgroud) 我理解在三个实例上调用复制构造函数
3.按值从函数返回对象时.
我有问题,如果在返回对象值时调用了复制构造函数,如果在函数中本地声明了对象,则不应该产生问题.
我的意思是复制构造函数是一个深拷贝,并将对象的引用作为参数
显式复制构造函数不允许使用类似的东西Foo foo = bar;
,并强制执行复制用法Foo foo(bar);
.此外,显式复制构造函数还禁止通过函数的值返回对象.但是,我尝试用大括号替换副本初始化,就像这样
struct Foo
{
Foo() = default;
explicit Foo(const Foo&) = default;
};
int main()
{
Foo bar;
Foo foo{bar}; // error here
}
Run Code Online (Sandbox Code Playgroud)
我收到了错误(g ++ 5.2)
错误:没有匹配函数来调用'Foo :: Foo(Foo&)'
或(clang ++)
错误:struct initializer中的多余元素
删除explicit
使得代码在g ++下可编译,clang ++仍然失败并出现相同的错误(感谢@Steephen).这里发生了什么?统一初始化是否被视为初始化列表构造函数(胜过所有其他构建函数)?但如果是这种情况,为什么程序在复制构造函数非显式时编译?
c++ copy-constructor language-lawyer uniform-initialization c++11
我将一个未命名的临时对象传递给使用const ref参数定义的函数.该类的副本是私有的,我收到编译错误.我不明白为什么在这种情况下调用复制构造函数.
class A {
public:
A(int i) {}
private:
A(const A&) {}
};
void f(const A& a)
{
}
int main()
{
f(A(1)); // <-- error here: 'A::A(const A&)' is private
}
Run Code Online (Sandbox Code Playgroud)
正如所料,当我将主要更改为:
A a(1);
f(a);
Run Code Online (Sandbox Code Playgroud)
有用.
编辑:编译器是gcc 4.1.2
所以基本上这段代码:
class A {
};
class B {
B (const B& b) {}
public:
B (){}
B (const A& a) {}
};
int main()
{
A a;
B b1(a); //OK
B b2 = a; //Error
}
Run Code Online (Sandbox Code Playgroud)
只生成一个错误B b2 = a
.那个错误是
错误:'B :: B(const B&)'是私有的
除了直接转换构造函数之外,为什么还要尝试调用复制构造函数?
从错误消息中可以清楚地看到B
创建了一个临时文件然后用于复制构造,但为什么呢?这个标准在哪里?
这段代码:
class X {
int member;
};
volatile X a;
X b = a;
Run Code Online (Sandbox Code Playgroud)
失败并出现错误:
prog.cpp:6:7: error: no matching function for call to ‘X::X(volatile X&)’
prog.cpp:6:7: note: candidates are:
prog.cpp:1:7: note: X::X()
prog.cpp:1:7: note: candidate expects 0 arguments, 1 provided
prog.cpp:1:7: note: X::X(const X&)
prog.cpp:1:7: note: no known conversion for argument 1 from ‘volatile X’ to ‘const X&’
Run Code Online (Sandbox Code Playgroud)
有什么办法可以让编译器为我生成易失性复制构造函数吗?
c++ ×10
copy-constructor ×10
c++11 ×4
constructor ×1
destructor ×1
gcc ×1
memcpy ×1
stdthread ×1
templates ×1
volatile ×1