C ++在指针上开始/结束(arr) - 没有用于调用'begin(int **&)'的匹配函数

时间:2016-12-08 09:39:13

标签: c++ arrays pointers

我想获得一个数组的长度。我有这段代码:

#include <iterator>
#include <iostream>
#include <string>
using namespace std;

void printArrLen(int arr[]);

int testArr [3] = {1, 4, 5};

int main() {
  printArrLen(testArr);
  cout << "main/testArr; Memory address: " << testArr << ", value: " << *testArr << endl;
  cout << end(testArr) << endl;
}

void printArrLen(int arr[]) {
  cout << "printArrLen/arr; Memory address: " << arr << ", value: " << *arr << endl;
  cout << "printArrLen/testArr; Memory address: " << testArr << ", value: " << *testArr << endl;
  // This works:
  cout << end(testArr) << endl;
  // This doesn't work - no matching function for call to 'end(int*&)':
  // cout << end(arr) << endl;
  // Doesn't work:
  // cout << "arrLen: " << end(arr) - begin(arr) << endl;    
}

输出:

printArrLen/arr; Memory address: 0x601318, value: 1
printArrLen/testArr; Memory address: 0x601318, value: 1
0x601324
main/testArr; Memory address: 0x601318, value: 1
0x601324

在printArrLen中取消注释cout << end(arr) << endl;会产生no matching function for call to 'end(int*&)'

我知道如果begin/end(arr)是指针,arr将无效。 为什么它们在printArrLen和main中的testArr上运行,如果testArr似乎也是指针呢?如何在printArrLen中证明testArr不是指针而arr是在它们似乎都包含内存地址的时候?

3 个答案:

答案 0 :(得分:2)

  

我知道如果arr是一个指针,开始/结束(arr)将无法工作。为什么它们在printArrLen和main中的testArr上运行,如果testArr似乎也是一个指针呢?

指针不是数组。

在您的代码中,

  • arr是已使用3个元素初始化的数组。
  • decays是数组参数。数组参数在数组printArrLen到指针的意义上是特殊的,因此实际传递给函数arr的是指针(到int testArr[] = {1, 4, 5}; 第一个元素)。

顺便说一句,初始化时不必提供数组大小。这也可以(并且更好):

{{1}}

答案 1 :(得分:1)

testArr不是指针,它是一个包含3元素的数组。

arr是一个指针 - 没有足够的知识使beginend工作,因为编译器不知道它指向一个数组(以及假设数组的大小是)

我的建议是:使用std::arraystd::vector,具体取决于您需要做什么。如果要使用旧式数组,请更改printArrLen以获取数组引用:

template <size_t N>
void printArrLen(int (&arr)[N]) {
    /* ... */
}

wandbox example

答案 2 :(得分:1)

  

我希望得到一个数组的长度。

     

[...]

void printArrLen(int arr[]);

不喜欢这样。此函数中的arr实际上是指向数组的第一个元素的指针。或者更确切地说,可能指向数组的第一个元素。它只是一个int*,可以指向任何地方。在任何情况下, 在函数内部都不再有大小信息。你根本无法得到它。

[]语法可以让您感到困惑。但是不要接受我的话 - 通过尝试这段代码来询问编译器:

void printArrLen(int arr[]) {}
void printArrLen(int* arr) {}

你会发现它会抱怨重新定义。

int testArr [3] = {1, 4, 5};

testArr,与上面的arr参数相比,一个数组,并且在其类型中包含大小信息。

int main() {
  printArrLen(testArr);

在这里,您向函数传递一个指向testArr的第一个元素的指针,即int*指向&#34; 1&#34;元件。

 // This works:
  cout << end(testArr) << endl;

因为testArr是一个数组。

  // This doesn't work - no matching function for call to 'end(int*&)':
  // cout << end(arr) << endl;

因为arr是指针。

如果数组的大小仅在运行时已知,则使用std::vector;如果在编译时已知数组std::array,则使用testArr。两个容器总是知道自己的大小。

  

如何在printArrLen中证明arr不是指针   和int main() { int i = 0; double d = 0.0; } 是什么时候它们似乎都包含一个内存地址?

这个问题没有看起来那么有意义。

考虑一下:

i

现在,你怎么能证明&#34; double不是d但是#include <typeinfo> #include <typeindex> #include <iostream> void printArrLen(int arr[]); int testArr [3] = {1, 4, 5}; int anotherTestArr [3] = {1, 4, 5}; int yetAnotherTestArr [4] = {1, 4, 5, 6}; int main() { printArrLen(testArr); } void printArrLen(int arr[]) { std::cout << (std::type_index(typeid(arr)) == std::type_index(typeid(testArr))) << "\n"; std::cout << (std::type_index(typeid(anotherTestArr)) == std::type_index(typeid(testArr))) << "\n"; std::cout << (std::type_index(typeid(yetAnotherTestArr)) == std::type_index(typeid(testArr))) << "\n"; }

答案是你没有必要证明&#34;它,因为,显然,你已经知道了。

从技术上讲,当然,你的问题还有另一个答案,那就是使用typeid ......

0
1
0

这对您没有任何直接用途,但具有很高的教育价值。它会打印出来:

-- drop table #me
create table #ME (memid int , EffectiveDate datetime , termdate datetime)

Insert into #ME values ('123','3-Dec-16','10-Jan-17')
Insert into #ME values ('123','11-Jan-17','6-Feb-17')
Insert into #ME values ('123','7-Feb-17','5-Mar-17')
Insert into #ME values ('123','8-Mar-17','15-Apr-17')
Insert into #ME values ('123','16-Apr-17','24-May-17')

--drop table #dim
select * from #ME
declare @StartDate datetime , @CutoffDate datetime

select @StartDate= min(effectivedate),@CutoffDate = max(termdate) From #me where termdate<>'9999-12-31 00:00:00.000'

SELECT d
 into #dim
FROM
(
  SELECT d = DATEADD(DAY, rn - 1, @StartDate)
  FROM 
  (
    SELECT TOP (DATEDIFF(DAY, @StartDate, @CutoffDate)) 
      rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
    FROM sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
    -- on my system this would support > 5 million days
    ORDER BY s1.[object_id]
  ) AS x
) AS y;

--drop table #MemEligibilityDateSpread

select MemID, D As DateSpread Into #MemEligibilityDateSpread From #Dim dim JOIN #me ME on dim.d  between ME.effectivedate and me.termdate 

--drop table #DateClasified

WITH CTE AS 
(
 SELECT MEmID,
        UniqueDate = DateSpread, 
        DateGroup  = DATEADD(dd, - ROW_NUMBER() OVER (PARTITION BY Memid ORDER BY Memid,DateSpread), DateSpread)
  FROM #MemEligibilityDateSpread
  GROUP BY Memid,DateSpread
)
--===== Now, if we find the MIN and MAX date for each DateGroup, we'll have the
     -- Start and End dates of each group of contiguous daes.  While we're at it,
     -- we can also figure out how many days are in each range of days.
 SELECT Memid,
        StartDate = MIN(UniqueDate),
        EndDate   = MAX(UniqueDate) 
   INTO #DateClasified
   FROM cte 
  GROUP BY Memid,DateGroup
  ORDER BY Memid,StartDate

select ME.MemID,ME.EffectiveDate,ME.TermDate,DC.StartDate,DC.EndDate from #DateClasified dc join #me ME ON  Me.MemID = dc.MemID 
        and (ME.EffectiveDate BETWEEN DC.StartDate AND DC.EndDate
                OR ME.TermDate BETWEEN DC.StartDate AND DC.EndDate) 

此示例演示了不同大小的数组是不同类型,指针是所有数组类型的不同类型。