C++ 唯一指针;为啥这个示例代码会出现编译错误?错误代码太长了,我无法指定

Posted

技术标签:

【中文标题】C++ 唯一指针;为啥这个示例代码会出现编译错误?错误代码太长了,我无法指定【英文标题】:C++ unique_ptr; Why this sample codes get compile error?? error codes are so long that I can't specify itC++ 唯一指针;为什么这个示例代码会出现编译错误?错误代码太长了,我无法指定 【发布时间】:2021-08-08 11:27:37 【问题描述】:

我现在正在研究智能指针,我只是在书中构建了示例代码。 但是当我像下面的代码一样使用unique_ptr 时,它会产生编译错误。错误码太长了,差点被剪掉了,写不完。

我想知道为什么这些代码出错了...请帮助我。

compiler and OS : g++ (Ubuntu 9.1.0-2ubuntu2~18.04) 9.1.0

我能找到的错误代码

/workspace/What_I_Learned/Cpp/53/53-4.cpp:23:30: error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream<char>’ and ‘std::unique_ptr<int>’)
   23 |  cout << "smart pointer 2: " << p2 << '\n';
      |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~ ~~
      |       |                         |
      |       std::basic_ostream<char>  std::unique_ptr<int>

/usr/include/c++/9/ostream:691:5: error: no type named ‘type’ in ‘struct std::enable_if<false, std::basic_ostream<char>&>’

我写的代码

#include <iostream>
#include <memory>

using namespace std;

int main(void) 
    unique_ptr<int> p1(new int(10));
    unique_ptr<int> p2;
    
    cout << "smart pointer 1: " << p1 << '\n';
    cout << "smart pointer 2: " << p2 << '\n';
    cout << "move to p2\n";
    
    p2 = move(p1);
    
    cout << "smart pointer 1: " << p1 << '\n';
    cout << "smart pointer 2: " << p2 << '\n';
    cout << "free memory\n";
    
    p2.reset();
    
    cout << "smart pointer 1: " << p1 << '\n';
    cout << "smart pointer 2: " << p2 << '\n';

我已经尝试过-std=g++11-std=g++14

【问题讨论】:

而不是提供来自编译器的最后一条错误消息(位于屏幕或窗口底部的那个),而是提供第一条错误消息。这可能会提供更多有关问题原因的信息。一般来说,当编译器在你的代码中遇到更多错误时,它会变得更加混乱——这意味着第一个错误消息之后的错误消息更可能不清楚。无论如何,C++ iostream 不支持std::unique_ptrs 的输入或输出。 您要打印什么?地址还是内容? (顺便说一句,哪本书?) 您是否要打印指针本身?然后使用例如p1.get()。或者创建一个&lt;&lt; 重载,将std::unique_ptr 模板作为第二个参数(通过(常量)引用!)并使用其get 函数来获取原始指针。 @Peter 感谢您提供的信息。我想把所有的错误从头到尾都写完,但是太长了,控制台窗口把它剪掉了将近 80%……我无法粘贴它。 【参考方案1】:

std::unique_otr 类型的对象没有 operator &lt;&lt;

如果你需要输出拥有的指针的值然后写

cout << "smart pointer 1: " << p1.get() << '\n';

如果类模板std::unique_ptr的模板参数是char,则需要将成员函数get的返回表达式转换为void *类型。例如

cout << "smart pointer 1: " << static_cast<void *>( p1.get() ) << '\n';

这是一个演示程序。

#include <iostream>
#include <memory>

int main() 

    std::unique_ptr<int> p1(new int( 10 ) );
    std::unique_ptr<char> p2( new char( 'A') );
    
    std::cout << "smart pointer 1: " << p1.get() << '\n';
    std::cout << "smart pointer 2: " << static_cast<void *>( p2.get() ) << '\n';

程序输出可能看起来像

smart pointer 1: 0x5593824d6e70
smart pointer 2: 0x5593824d6e90

如果 std::unique_ptr&lt;char&gt; 类型的对象的拥有指针在没有强制转换的情况下输出,那么它将作为 C 字符串输出,而不是输出其存储的值(地址)。

如果您需要输出类模板std::unique_ptr的对象的指向值,那么只需应用解引用运算符即可。

例如

cout << "smart pointer 1: " << *p1 << '\n';

这是一个演示程序

#include <iostream>
#include <memory>

int main() 

    std::unique_ptr<int> p1(new int( 10 ) );
    std::unique_ptr<char> p2( new char( 'A') );
    
    std::cout << "the value of the smart pointer 1: " << *p1 << '\n';
    std::cout << "the value of the smart pointer 2: " << *p2 << '\n';

程序输出是

the value of the smart pointer 1: 10
the value of the smart pointer 2: A

在输出一个指向的值之前可以检查类模板std::unique_ptr的对象是否不存储类似的空指针

if ( p1 )

    std::cout << "the value of the smart pointer 1: " << *p1 << '\n';

if ( p2 )

    std::cout << "the value of the smart pointer 2: " << *p2 << '\n';
       

【讨论】:

【参考方案2】:

您正在将unique_ptr 对象传递给cout,因为没有适当的重载可用,它不知道如何处理它。如果要打印指针值,则需要这样做:

std::cout << "P: " << (void *)p1.get() << std::endl;

如果你想打印它指向的值,你当然可以这样做:

std::cout << "*P: " << *p1 << std::endl;

但在 p2 的情况下,您将取消对 nullptr 的引用,这是无效的,导致未定义的行为。

【讨论】:

【参考方案3】:

错误消息告诉您std::unique_ptr 没有operator &lt;&lt; 过载。你可以做的是

std::cout << "smart pointer dereferenced: " << *p1 << '\n';

请注意,如果智能指针处于空状态,则这是未定义的行为。

附带说明,考虑使用std::make_unique&lt;int&gt;(42) 来初始化std::unique_ptr(如果C++14 可用),因为它封装了原始new

【讨论】:

或者p1.get(),如果你对实际的指针值感兴趣的话。 嗯,这是在@Devolus 答案中:) 不会添加。可能只是更好的答案。

以上是关于C++ 唯一指针;为啥这个示例代码会出现编译错误?错误代码太长了,我无法指定的主要内容,如果未能解决你的问题,请参考以下文章

为啥在将唯一指针插入无序映射时 C++ 会给我一个错误?

为啥不能编译这个 C++ 模板代码?

C++ 为啥我不能将此指针保存到引用?

为啥这个向量代码会出现分段错误?

为啥我的代码会崩溃?

为啥这个程序在调用函数时会出现分段错误?