gcc 的奇怪行为。带有 和 = 的 C++ 对象定义是不是相等?

Posted

技术标签:

【中文标题】gcc 的奇怪行为。带有 和 = 的 C++ 对象定义是不是相等?【英文标题】:Strange behavior of gcc. Are C++ object definitions with and = equal or not?gcc 的奇怪行为。带有 和 = 的 C++ 对象定义是否相等? 【发布时间】:2020-08-08 10:25:17 【问题描述】:

我正在测试将 Processing 中完成的模拟转换为 C++ 的可能性。 但奇怪的事情发生了:

class World 
  public:
    sarray<pAnt>    dummy1  new array<pAnt>(10) ;//OK
    sarray<pAnt>    dummy2 = new array<pAnt>(10);  //Compiler error?!?!?!*
    smatrix<pAnt>   dummyWorld1  new matrix<pAnt>(100,100) ;//OK
    smatrix<pAnt>   dummyWorld2 = new matrix<pAnt>(100,100);//OK
    smatrix<int>    ants = new matrix<int>(50,2);// OK
...
;

错误:

/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/klasaWorld.pde.cpp:27:

错误:无法绑定类型的非常量左值引用 'Processing::sarrayProcessing::ptr&' 到类型的右值 ‘Processing::sarrayProcessing::ptr’

 sarray<pAnt>    dummy2 = new array<pAnt>(10) ;//Compiler error?!?

“详细”编译器输出:

[1/2 3.5/sec] 构建 CXX 对象 CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o 失败的: CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o /usr/bin/g++ -DDEF_MAXTHREADS=16 -DMULTITR -DVERSION_NUM=0.1 -I/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc -I/home/borkowsk/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/../../scripts/../lib/include -I/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux -I/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux/INCLUDE --verbose -std=c++11 -pthread -MD -MT CMakeFiles/MROWKI_0。 1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -MF CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o.d -o CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -c /data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp 使用内置规范。 COLLECT_GCC=/usr/bin/g++ OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 目标: x86_64-linux-gnu 配置:../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada, c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux- gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable- nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object - -disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto -- enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic - -enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux- gnu 线程模型:posix gcc 版本 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) COLLECT_GCC_OPTIONS='-D' 'DEF_MAXTHREADS=16' '-D' 'MULTITR' '-D' 'VERSION_NUM=0.1' '-I' '/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc' '-一世' '/home/borkowsk/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/../../scripts/../lib/include' '-I' '/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux' '-I' '/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux/INCLUDE' '-v' '-std=c++11' '-pthread' '-MD' '-MT' 'CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o' '-MF' 'CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o.d' '-o' 'CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/7/cc1plus -quiet -v -I /data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc -I /home/borkowsk/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/../../scripts/../lib/include -I /data/wb/SCC/__working_copies/symShell2/WBRTM_Linux -I /data/wb/SCC/__working_copies/symShell2/WBRTM_Linux/INCLUDE -imultiarch x86_64-linux-gnu -MD CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.d -MF CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o.d -MT CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -D_GNU_SOURCE -D_REENTRANT -D DEF_MAXTHREADS=16 -D MULTITR -D VERSION_NUM=0.1 /data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp -quiet -dumpbase project_at_once.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -std=c++11 -version -fstack-protector-strong -Wformat -Wformat-security -o /tmp/ccaH1ylE.s

GNU C++11 (Ubuntu 7.5.0-3ubuntu1~18.04) 版本 7.5.0 (x86_64-linux-gnu) GNU C 版本 7.5.0、GMP 版本 6.1.2、MPFR 版本 4.0.1、MPC 版本 1.1.0、isl 版本 isl-0.19-GMP 编译 ^

这是从我的项目中提取的问题。看起来一行是有罪的,但我不明白为什么:-)

#include <memory>

namespace Processing

   
template<class T>
class ptr

      //std::shared_ptr<T> _ptr;
  public:
      ptr();
      ptr(ptr<T>&);
      //ptr(const ptr<T>&);//This removes the error, but can not be implemented properly!
;

template<class T>
class array
     
      //T* content;
  public:
      ~array();
      array(size_t N);
;

template<class T>
class sarray
     // When the following line is commented out the error disapper!
      // so what is missing in ptr<T> ?  
      ptr< array<T> > _arr;//opaque smart ptr to array
      //std::shared_ptr< array<T> > _arr;//std smart pointer is OK
  public:
      ~sarray()
      sarray()
      sarray(array<T>* tab);
      sarray<T>& operator = (array<T>* tab);
;



using namespace Processing;


void example()
  
  sarray<bool>          test1 = new array<bool>(2);// Compiler error?
  sarray<bool>          test2;

  test2 = new array<bool>(2);//OK
  
  sarray<bool>   test3  new array<bool>(2) ;//OK      

【问题讨论】:

添加sarray&lt;T&gt;&amp; sarray::operator = (array&lt;T&gt;* tab);后,它分两个阶段工作,但不是一个阶段:-o sarray&lt;bool&gt; test; //sarray&lt;bool&gt; test = new array&lt;bool&gt;(2);// Compiler error test = new array&lt;bool&gt;(2);//OK sarray&lt;bool&gt; test2 new array&lt;bool&gt;(2) ;//OK sarray&lt;pRGB&gt; dummy; //sarray&lt;pRGB&gt; dummy = new array&lt;pRGB&gt;(Side);// Compiler error dummy = new array&lt;pRGB&gt;(Side);//OK sarray&lt;pRGB&gt; dummy1 new array&lt;pRGB&gt;(Side) ;//OK @rustyx - 好的,我有可编译的示例,但是如何在此处提供文件? @WojciechT.Borkowski “我有可编译的示例,但如何在此处提供文件?” - 只需编辑您的问题并粘贴代码。 @WojciechT.Borkowski 你的新代码更好,但距离minimal reproducible example 还差得很远。仍然有很多代码与您的问题完全无关,只是噪音,使我们(和您)更难看到问题。这是一个正确的minimal reproducible example:godbolt.org/z/jqo7aq 我已经通过删除我怀疑与错误无关的行来达到这一点;如果错误消息保持不变,我将删除该行,如果它更改了错误消息,我将其放回。这就是您在此处发布之前应该做的事情。无论如何,我投票决定重新开放,如果重新开放,我会回答。 X x = y;复制初始化。即使副本被优化掉(直到 C++17),它也需要一个副本构造函数。 【参考方案1】:

sarray&lt;pAnt&gt; dummy2 = new array&lt;pAnt&gt;(10);复制初始化语法。

语义上类似于sarray&lt;pAnt&gt; dummy2( sarray&lt;pAnt&gt;( new array&lt;pAnt&gt;(10) ) );(C++17 前)。

sarray 没有用户定义的copy constructor,所以它得到一个隐式的,它执行成员明智的复制。

问题是,ptr 作为成员之一,确实有一个用户定义的复制构造函数,ptr(ptr&lt;T&gt;&amp;)。从技术上讲,复制构造函数可以采用非常量引用。实际上它是rarely useful,因为一个非常量引用will not bind to a temporary。

因此出现错误 - cannot bind non-const lvalue reference of type ‘...ptr&lt;Ant&gt;&amp;’ to an rvalue of type ‘ptr&lt;Ant&gt;’

解决方案可能很简单 - 将笨拙的复制构造函数更改为移动构造函数 ptr(ptr&lt;T&gt;&amp;&amp;)(或添加一个)。

附加说明:sarray 似乎有一个用户定义的析构函数。根据rule of 3/5/0,它可能还需要一个用户定义的副本和/或移动构造函数。

【讨论】:

谢谢。我是科学家,不是专业程序员,但我使用 C++ 已经 20 多年了。无论如何我都不知道这种初始化工作如此奇怪:-)

以上是关于gcc 的奇怪行为。带有 和 = 的 C++ 对象定义是不是相等?的主要内容,如果未能解决你的问题,请参考以下文章

使用 SWIG 在 Python 中 C++ 类的奇怪行为

当数组是函数参数时,矩阵乘法中的 Gcc 自动向量化奇怪行为

GCC `-fsanitize=bounds` 与`std::array` 的奇怪行为

gcc 4.6 编译器的奇怪行为

Visual Studio C++ 编译器在局部变量对象上的奇怪行为

如何使用带有“-fomp”和“-pg -fprofile-create”的 gcc/gprof 分析 c++?