C++11 std::promise 从线程返回 std::string,数据指针看起来已复制未移动

标签 c++ multithreading c++11 thread-safety promise

我开始使用 C++11 标准和内置线程。根据我在获得 future 值时收集到的信息,它是使用移动运算符完成的,将所有权从原始对象中移走(就像旧的 auto_ptr 曾经在赋值时所做的那样)。我通过在线程期间打印出 std::string 对象内的 char 数组的指针并在 main 中接收到它后打印指针来测试这一点。但是,指针不同。如果有人能告诉我为什么他们在这个简单的代码中不同以及代码必须是什么样子才能使它们相等,我将不胜感激:

#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <string>
#include <thread>
#include <future>
using namespace std;
void thrfut(promise<string>&& promReceived)
{
    string strObj("Hello from future");
    cout << "Address of char array inside string inside of thread " << (void*)strObj.data() << endl;
    promReceived.set_value(strObj);
}
int main(int argc, char** argv) 
{
    promise<string> promiseOfText;
    future<string> futureText = promiseOfText.get_future(); // has to be before creating thread if the promise is passed rvalue reference, should be moved on calling get or not ? 
    thread threadHandlingPromise(&thrfut, std::move(promiseOfText));
    string stringReceived = futureText.get();
    cout << "Received from promise through thread: " << stringReceived  << endl;
    cout << "Address of of char array inside string received from promise in main " << (void*)stringReceived.data() << endl;
    threadHandlingPromise.join(); 
    return 0;
}

这是一个示例输出

Address of char array inside string inside of thread 0x10ebc9be1
Received from promise through thread: Hello from future
Address of of char array inside string received from promise in main 0x7fff510f68c9

仅供引用:OS X 10.9.1 w/Xcode 5 clang++ in Netbeans 8.0 其他人在 Ubuntu 和 Windows 上运行代码并返回相同的地址。

编辑(引用答案中的评论)* * * * *

我试过这个:

struct MYC 
{   MYC() = default;
    ~MYC() { delete _pInt; };
    MYC(const MYC & myc) { puts("MYC copy"); _pInt = nullptr; if(myc._pInt != nullptr) {   _pInt = new int{*myc._pInt}; } }  
    MYC(MYC && myc) { puts("MYC move"); delete _pInt; _pInt = myc._pInt; myc._pInt = nullptr; }
    void setMe(int value) { delete _pInt; _pInt = new int{value} ; }
    int * _pInt = nullptr;
};
void thrfut(promise<MYC>&& promReceived)
{
    MYC obj;
    obj.setMe(5);
    cout << "Address of int inside MYC inside thread " << (void*)obj._pInt << endl;
    promReceived.set_value(std::move(obj));    
}
int main(int argc, char** argv) 
{
    promise<MYC> promiseOfMYC;
    future<MYC> futureMYC = promiseOfMYC.get_future();  
    thread threadHandlingPromise(&thrfut, std::move(promiseOfMYC));
    auto mycReceived = futureMYC.get();
    cout << "Address of int inside MYC received from promise in main " << (void*)mycReceived._pInt << endl;
    cout << "Value of int inside MYC received from promise in main " << *(mycReceived._pInt) << endl;
    threadHandlingPromise.join(); 
    return 0;
}

得到:

Address of int inside MYC inside thread 0x7fd1b9c00110
MYC move
MYC move
Address of int inside MYC received from promise in main 0x7fd1b9c00110
Value of int inside MYC received from promise in main 5

这证实了非字符串类的移动动态。

最佳答案

编辑

终于想起GNU libstdc++ std::string使用引用计数。也许这解释了什么?? (虽然不是全部)

原始答案

(1)确实是系统依赖

$ g++48 promiseStr.cpp -o promiseStr -Wall -Wextra -std=c++0x -O0 -g3 -pthread && echo OK
OK
$ ./promiseStr
Address of char array inside string inside of thread 0x7f4b400008d8
Received from promise through thread: Hello from future
Address of of char array inside string received from promise in main 0x7f4b400008d8

$ lsb_release -a
LSB Version: (snip)
Distributor ID: Ubuntu
Description:    Ubuntu 12.04.2 LTS
Release:        12.04
Codename:       precise
$ g++48 --version
g++48 (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

(2) future<T>::get()返回 T不是&&T , 所以 stringReceived可能是复制构造的。

(3) 你不妨试试ltrace在 Linux 上查看引擎盖下发生了什么(抱歉,我没有 OS X 机器。)

$ ltrace -n2 -f -C ./promiseStr 2>&1 | grep basic_string
[pid 6899]       std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)(0x7f486c17fde0, 0x406ea0, 0x7f486c17fdef, 0x7f486c180700, 0x7f486c180700) = 0x7f48640008d8
[pid 6899]             std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)(0x244e0b0, 0x7f486c17fde0, 0x7f4864000900, 0x7f486c17fd90, 0x7f486c17fd20) = 0x7f48640008d8
[pid 6899]         std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(0x7f486c17fde0, 0xffffffff, 0, 0x7f4864000028, 0x244e038 <unfinished ...>
[pid 6899]         <... std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() resumed> ) = 1
[pid 6898]   std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string&&)(0x7fff5c17ece0, 0x244e0b0, 0x244e0b0, -1, 0x244e038) = 0x7f486cf723d8
[pid 6898]   std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(0x244e0b0, 1, 0x244e0a0, -1, 0x244e060) = 0x244e0b0
[pid 6898]   std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)(0x60bd40, 0x7fff5c17ece0, 0x7fff5c17ece0, 0x203a6461, 0x7f486c53cab0) = 0x60bd40
[pid 6898]       std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(0x7fff5c17ece0, 0x7f486c759250, 0x7f486c180700, 0x7f486c759250, 0) = 0

关于C++11 std::promise 从线程返回 std::string,数据指针看起来已复制未移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21225292/

相关文章:

java - 第一次调用一个方法,当数据有变化时再次调用该方法

c++ - 有没有办法手动扩展可变参数模板?

c++ - std::is_base_of 用于模板类

c++ - 避免使用模板分配抽象类型

c++ - 我输出中的 D3D11 INFO 行是什么意思?

c++ - 基于 UDP 的 Asteroids 游戏待办事项 list

java - 使用带有多线程的camel框架进行组件测试

multithreading - Akka:如何确保已收到消息?

c++ - 正确锁定从多个线程调用其自己的成员函数的类。 (我需要锁定访问 "this"指针吗?)

c++ - 无法构建 boost 1.64.0 b2.exe Visual Studio 2017