Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 惯用(例如TBB的线程_可枚举_特定)是否在原始对象上移动赋值调用析构函数_C++_Move_Tbb - Fatal编程技术网

C++ 惯用(例如TBB的线程_可枚举_特定)是否在原始对象上移动赋值调用析构函数

C++ 惯用(例如TBB的线程_可枚举_特定)是否在原始对象上移动赋值调用析构函数,c++,move,tbb,C++,Move,Tbb,假设我正在使用一个惯用的Cpp库,例如Intel的TBB,并且在某些类中有一个就地成员,例如TsCountersType(计数器);。这样的成员由其默认构造函数(如果存在)自动初始化,否则编译错误,除非我自己的KMeans构造函数通过直接调用其构造函数来显式初始化它 然后,如果我在一个普通的非构造函数方法(例如init)中将通过调用构造函数值创建的一个新值分配给成员字段,那么可以安全地假设什么呢 我知道在这种情况下,赋值的右边是右值,因此将调用move赋值运算符。 我认为可以安全地假设,在将新对

假设我正在使用一个惯用的Cpp库,例如Intel的TBB,并且在某些类中有一个就地成员,例如TsCountersType(计数器);。这样的成员由其默认构造函数(如果存在)自动初始化,否则编译错误,除非我自己的KMeans构造函数通过直接调用其构造函数来显式初始化它

然后,如果我在一个普通的非构造函数方法(例如init)中将通过调用构造函数值创建的一个新值分配给成员字段,那么可以安全地假设什么呢

我知道在这种情况下,赋值的右边是右值,因此将调用move赋值运算符。 我认为可以安全地假设,在将新对象移动到内存位置之前,行为良好的惯用Cpp代码应该调用原始对象的(例如)析构函数。但这样的假设正确吗? 默认的移动分配操作符是什么?它在移入之前是否对原始对象调用析构函数?这是一个相关的问题,还是只有在其他条件中没有定义显式析构函数时,编译器才会创建默认的移动赋值运算符

如果是这样的话,如果我有一个类似于TBB的场景,在这个场景中,我没有TsCountersType,而是使用一个唯一的ptr和默认的所有其他构造函数、析构函数、移动赋值等简单的自定义tipe,会发生什么…。那么,唯一的ptr什么时候会超出范围? 特别是在TBB的情况下,我可以假设它发生在他们的:自C++11以来支持的情况下。将“其他”的内容原封不动地移动到此*中。另一个处于未指明状态,但可以安全销毁

示例代码:

类KMeans { 私人: //... //线程特定计数器 typedef std::pair TSCounterType; typedef tbb::可枚举线程特定TsCountersType; TsCountersType\u ts\u计数器; 公众: //... KMeans:_tbbInittbb::task_scheduler_init::automatic{} 虚拟空间初始化std::size\u t points,std::size\u t k,std::size\u t iters { //当_ts_计数器被新对象替换时,会自动对原始对象调用析构函数 _ts_counters=TsCountersTypestd::make_pairstd::vectork,std::vectork; } }; 考虑以下代码:

#include<iostream>

struct S
{
    S() { std::cout << __PRETTY_FUNCTION__ << std::endl;}
    S(S const &) { std::cout << __PRETTY_FUNCTION__ << std::endl;}
    S(S&&) { std::cout << __PRETTY_FUNCTION__ << std::endl;}
    S& operator=(S const &) { std::cout << __PRETTY_FUNCTION__ << std::endl; return *this;}
    S& operator=(S&&) { std::cout << __PRETTY_FUNCTION__ << std::endl; return *this;}
    ~S() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

struct W
{
    W() : s{} {}
    void init() { s = S{}; }
private:
    S s;
};

int main()
{
    W w{};
    w.init();
}
那么,到底发生了什么:

调用W的constructor,默认初始化 临时S是默认构造的,并立即从移动到W::S成员中 临时对象现在在init退出之前被销毁 W::s在主出口被破坏。
请,每个问题只问一个问题。将新对象移动到内存位置是什么意思?在C++中不存在内存中的移动对象。虽然我同意你们的观点,但这些问题都是高度集成的,如果从语义的角度理解它,那么T.I.A.D.NIILANGRG就没有多大意义。创建新对象TsCountersType。。。作为右值,然后将其移动到_ts_计数器。当然,实际的实现不需要将任何东西移动到任何地方。这里,调用TsCounterType的move assignment op.,如果存在copy assign。否则。按照惯例,它应该保证1左侧计数器的内容与=之前的右侧计数器的内容相同,2右侧计数器将保持某种状态为空、未指定等,可能与=之前的内容不同。_ts_计数器不涉及析构函数。内存中没有移动的对象,它不存在。实际操作取决于移动分配的定义。TscontersType的操作。似乎使用默认的移动构造函数,时间对象不会被破坏。请参阅:确实如此,您可以在输出中看到它。有两个物体被构造,两个被破坏。是的,我们在另一个问题中解决了这个问题。谢谢
S::S()
S::S()
S &S::operator=(S &&)
S::~S()
S::~S()